Problem/Motivation
Media entities (and others) can be deleted even if they are being referenced.
A consequence of this (intentional) behavior is that sites using Entity Embed are no longer showing the embedded entity; because there is nothing to show anymore!
By itself, this is not a problem, but what's worse is that it's impossible for a content author to delete the embed of the now no longer existing entity! The only way for a content author to do this is to switch to source mode (if they're even allowed to do so).
Keeping these embeds of non-existing entities results in error messages in Drupal's logs. And it may even result in errors preventing updates: #2914468: EntityNotFoundException in EntityEmbedFilter ("Unable to load embedded file entity").
Proposed resolution
Rather than rendering the embedded entity, generate a <img> tag with an icon to convey the entity is missing:

Remaining tasks
Determine if we want a follow-up for a cron job that periodically inspects the default revision of all entities of all entity types with text fields, to automatically surface these.
User interface changes
Embeds of missing entities are made accessible (and visible) in both CKEditor (for the content authors, so they can fix it) and the filtered text (for the readers, so they can still make sense of the text, and potentially report it to the site owner).
API changes
None.
Data model changes
| Comment | File | Size | Author |
|---|---|---|---|
| #29 | interdiff-25-29.txt | 2.29 KB | marcoscano |
| #29 | 2752253-29.patch | 3.31 KB | marcoscano |
| #25 | 2982322-25.patch | 1.15 KB | wim leers |
| #25 | interdiff.txt | 1.01 KB | wim leers |
| #21 | Screen Shot 2018-12-04 at 11.16.54.png | 63.98 KB | wim leers |
Comments
Comment #2
anybodyComment #3
marcoscanoThat would be indeed a good thing to have. I'd even adventure to say it is a bug that we don't show an inconsistent state clearly to the user.
Comment #4
dave reidAgreed, ideas on what should be displayed? What should we display when the entity was loadable but the user doesn't have access to it? Should that still remain not visible? Can we ensure that this only happens when being used in the WYSIWYG context and not during normal rendering? I don't think I was able to solve that latter part originally, so that's the key issue here.
Comment #5
marcoscanoOh true, we shouldn't mess with the normal rendering, and this might be tricky to differentiate...
Maybe we can simplify the approach if we show an "error/broken" element in both cases, but only for users with a specific admin permission? This way only selected users would see the errors everywhere, but supposedly they are the ones that can correct them too.
Comment #6
wim leersComment #7
wim leers@gngn followed up at #2914468-16: EntityNotFoundException in EntityEmbedFilter ("Unable to load embedded file entity"):
(emphasis mine)
My response at #2914468-17: EntityNotFoundException in EntityEmbedFilter ("Unable to load embedded file entity"):
That means that without this, we're left with a massive, major usability hole. The ideal solution I described in #17 is not feasible in the short or medium term, which leaves this issue as the only short term solution. Hence bumping to . Rewrote the issue summary to assemble all information in one place.
Module maintainers, please credit @gngn on this issue!
Comment #8
wim leers#3015730: Demote EntityNotFoundException from error to warning was opened a few days ago, it's a duplicate of this.
Comment #9
efpapado commentedI'm proposing another approach:
<drupal-entity />, overall or by entity type. VBO could be considered also.Some more explanation:
1) We could introduce a new table, named like
entity_embed_brokenorentity_embed_orphan(s)with these fields:(
uuidcould also be used)Each time we end up to an EntityNotFoundException, we db_merge a row on that table.
A message could be shown to the user (permission-based) also.
2) A new report page can list all the existing broken/orphan embeds. So a user with proper permission can manually visit the entities and edit them.
Maybe, additionally, another row in status report, stating that there are orphaned entity embeds.
3) I haven't thought yet how this could be implemented.
4) The "clean up" action (UI batch + drush) can edit the host entities and remove the broken embeds. It can be done by entity type.
Also we can give several options here, e.g. about revisions, update timestamp etc.
What would you think about an approach like this?
Comment #10
oknateThat approach sounds awesome, but perhaps would be better in a separate module entity_embed_garbage_collection.
Comment #11
wim leers#9 that sounds lovely but …
Hoping @marcoscano can chime in on this one :)
Comment #12
marcoscanoYes, I agree that we should try to keep the scope here separate from the "data integrity" problemspace, which can quickly go out of hand.
Entity Usage has currently a feature where you can opt-in to a warning message being shown to users whenever an entity (which is referenced from other places) is being deleted. It doesn't prevent deletion, but if necessary custom/contrib code could leverage the info stored there to do that without much overhead.
Entity Embed however should provide a sensible alternative to users when broken relationships do happen. I think figuring out a way to display a placeholder to admins (basically improving the UX for manually removing the reference) would be the ideal path forward to this issue.
Comment #13
wim leers+1
Comment #14
marcoscanoIf it serves as inspiration, this is what core does when an embedded image is missing:
It's worth noting though that this problem in core is significantly mitigated by the fact that there is *no* UI for deleting a permanent file in drupal core. You would only get to the "broken" scenario above if you use some contrib/custom code to somehow get an image deleted outside of the context of the node it was embedded into.
Comment #15
wim leersThat's not what that is though; it's
\Drupal\filter\Plugin\Filter\FilterHtmlImageSecurestripping away images that it considers insecure.Nonetheless, I agree, that could be an example to look at. I'd be careful though; because that also means that it's going to be difficult for a content author to distinguish between "image still exists but is insecure" and "image does not exist anymore"
Comment #16
marcoscanoHa, interesting! True, it is the filter adding the placeholder if the image is considere insecure or (as in this case) couldn't be retrieved. (I did remove the file entity by code before taking that screenshot).
I agree that a unique placeholder will make more sense in any case.
Thanks!
Comment #17
wim leersRather than make it behave differently in the text editor and in the filtered text shown to the end user, I think it makes more sense to have it behave the same in both situations.
Not only because the existing filter system does not allow to specify arbitrary context (we'd need to know whether we're filtering "for real" or "for preview inside the text editor"). But also because when the end user is reading text and some embedded entity is just omitted without any indication, the text will probably seem broken (since it is likely referring to the embedded entity).
I propose this:

(This is reusing core Media's
core/modules/media/images/icons/no-thumbnail.pngicon.)Comment #18
marcoscano#17: +1!
Minor: would it be worth adding an alt text to this image such as
alt="Deleted content"or something like that?Comment #19
wim leers#18: yeah, I was already doing exactly that, as well as setting
width+heightattributes and copying the image from the core module into the Entity Embed module.Comment #20
wim leersActually … that icon has existed in Drupal core since June 2017 (in #2831937: Add "Image" MediaSource plugin), for nearly 1.5 years, it shipped with Drupal 8.4. Drupal >=8.5 (8.5+8.6) are the only supported Drupal core releases. So … I think we don't actually need to copy the file over; we can assume it exists.
Comment #21
wim leersAnd here's a less confusing screenshot for in the IS.
Comment #22
wim leersComment #23
marcoscano+1
👏
Super nitpick: Can we add a final period to the alt sentence? :)
It apparently helps by telling screen readers to take a short break before proceeding.
https://ux.shopify.com/considerations-when-writing-alt-text-a9c1985a8204...
Comment #24
wim leers#23.2: hah, that's exactly why I didn't add a period! I don't feel strongly either way, and we can change this based on real-world feedback.
Also, that string should be translated! 😅
Comment #25
wim leersComment #26
marcoscano:)
Comment #27
wim leersI think this still needs test coverage in
\Drupal\Tests\entity_embed\Functional\EntityEmbedFilterTest?Comment #28
marcoscanoworking on it.
Comment #29
marcoscanoComment #30
wim leersIMHO this is ready now, but it'd be great to get +1s from others.
Comment #31
phenaproxima+1 RTBC. Nice improvement.
Comment #33
wim leers🎉
Comment #34
gngn commentedThank you, that's great.
@Wim Leers sadly I wasn't credited...
Comment #35
anybodyThank you very very much for fixing this issue! This is great news and I'm looking forward to the next stable release :)
Comment #36
wim leers@gngn: Oh :| I'm very sorry, @gngn!
I can't change the commit, but I've added issue credit for you now! :)
Comment #38
gngn commented@Wim Leers: thank you!
Comment #39
wim leersThe #3019308: Follow-up for #2982322: set `title` attribute for missing entities, to provide useful information upon mouseover follow-up just got committed :)
Comment #40
larowlanWould you support a patch here to make it so that the option to output the image to non-admins is configurable? (in a new issue of course)
Comment #41
oknateThere's a follow-up issue #3065054: Add permission to allow 'missing media' to be hidden from anonymous users, perhaps we could take up the discussion of modification there?