Problem/Motivation
The EntityEmbedDialog lacks fields for setting alt and title text. This is essential for sites that need to meet 508 accessibility compliance. Users need to go back to the Media list, edit the entity, then add the alt text.
Proposed resolution
- Add an alt text field to the final step of the embed dialog when:
- The media source is 'image'.
- When "Enable Alt field" is enabled on the media's source image field.
- Add a title text field to the final step of the embed dialog when:
- The media source is 'image'.
- When "Enable Title field" is enabled on the media's source image field.
- The alt field will be required when the media's image field requires it.
- The title field will be required when the media's image field requires it.
- The title and alt field will not affect the values saved in the database. They are per embed overrides.
- If alt attribute is set on the drupal-entity embed code, it will override the value of the media's image field's alt property as well as the media thumbnail's alt text
- If title attribute is set on the drupal-entity embed code, it will override the value of the media's image field's title property as the media thumbnail's title text
- Allow overriding the alt property to a blank string in the same way that the core ImageFieldFormatter does, using double quotes ("").
- The same entity should be able to embedded with different alt text.
Remaining tasks
- Review
User interface changes
The fields are added to the dialog, wen relevant. That looks like this:
API changes
None.
Data model changes
None. (Now the alt
and title
attributes can appear on <drupal-entity>
automatically, rather than this requiring manually modifying the HTML in CKEditor's source mode.)
Comment | File | Size | Author |
---|---|---|---|
#116 | 2924391-116.patch | 41.2 KB | Wim Leers |
| |||
#116 | interdiff.txt | 1.21 KB | Wim Leers |
#114 | 2924391-114.patch | 41.64 KB | Wim Leers |
| |||
#114 | interdiff.txt | 4.91 KB | Wim Leers |
#113 | interdiff.txt | 1.21 KB | Wim Leers |
Comments
Comment #2
jds1Comment #3
cilefen CreditAttribution: cilefen at Institute for Advanced Study commentedComment #4
cilefen CreditAttribution: cilefen at Institute for Advanced Study commentedWhat media modules are you using? What's in core now doesn't have its own upload widget as such and is hidden.
Comment #5
jds1Thank you for responding.
Media Entity
Media Entity Image
Entity Browser
Embed
Entity Embed
My comment over here on Media Entity Image led me here: https://www.drupal.org/node/2850169#comment-12340870
Attaching a screenshot of an embed screen without an alt field.
Comment #6
marcoscanoThis is definitely not a core issue, I'm guessing it's more related to Entity Browser, but it could be Entity Embed instead, not sure.
I'd bet it is possible to achieve what you are looking for, but TBH I don't remember off the top of my head the steps to do that. My recommendation would be for you to research a bit the issue queue for Entity Browser and/or Entity Embed how to expose the Alt field when you are embedding a media entity.
If you can't find anything conclusive, try explaining here the steps to reproduce your scenario on a clean install, so hopefully someone can spot the part of the process that should be changed (or the bug, if it exists).
Comment #7
jds1Hi @marcoscano. Thank you for responding. I did this on a clean install and got the same kind of situation with no alt text. No need for a screenshot since it looks exactly the same as the one already attached to this issue. Here are the steps I take to repro:
1. Create Image bundle/add image field.
2. Create entity browser view to hook up to actual entity browser.
3. Create entity browser, iframe widget, no selection option, with two tabs: Upload Images (image upload widget) and Embed Media (uses entity browser view I just created).
4. Create text editor embed button that uses media bundle and entity browser I just created. No restrictions on bundles/display modes when creating text editor embed button.
5. Hook text editor embed button up to text format. Make sure "alt" tag is allowed in "allowed tags" area.
6. Create new page, click embed button, use existing media, no alt text in "Embed Media" screen (original screenshot, embed-media-no-alt.png). Thumbnail formatter.
7. Save node. Alt text is replaced with "Thumbnail" text (no-alt-text-in-embed.png). I know this is a nonissue if I use a different display mode, so might be separate issue.
8. Edit page, click embed button, upload new image.
9. Use "Embed" or "Media Image" display mode. No Alt text available. Can't embed uploaded image with alt text.
If I go back and use the "Embed" or "Media Image" format with my existing media where I uploaded through the "Add New Media" interface and put in alt text, I get the alt text when I save the page.
Please let me know if I can provide any additional information or if a screencast would be helpful here.
Thank you!
Comment #8
cilefen CreditAttribution: cilefen at Institute for Advanced Study commented@if-jds Clean install refers to "no contributed modules" modules usually, as in "core only".Comment #9
cilefen CreditAttribution: cilefen at Institute for Advanced Study commentedForget that...not in this case.
Comment #10
jds1It looks like there's a sandbox module that fixes this problem, but I would prefer for this to get integrated into the correct place. Is it the core image module that's the problem?
See https://www.drupal.org/project/drupal/issues/1291262#comment-12302748 for more info.
Thanks all!
Comment #11
jds1Moving this to Entity Embed queue: fairly certain that this issue is happening at the embed level.
Comment #12
jds1Comment #13
jds1Comment #14
frankdesign CreditAttribution: frankdesign commentedThis is not only an Entity Embed issue. It's also happening with Entity Browser. I have created a content type with a Media Image field. The Form Display I am using for that field is 'Entity Browser' using two widgets - 'Upload images as media items' and 'View'. For both of these options when I upload a new Media Image or Browse Existing Media Images, when I select the desired image, the image is placed in the Media Image field and displays only the file name and an Edit and Remove button. To enter the ALT text, I need to click on the Edit button after placing the image - which content editors are not going to do. More worryingly, I can save the node without entering the 'required' Alt text.
BTW, I'm not using Entity Embed. I have recreated this on a new install of Drupal 8.5.5 and 8.6.0-alpha-1 with only Media, Entity Browser and Chaos Tools enabled in addition to the Standard Install.
Anyone got any ideas? Also, where should this issue be posted?
F
Comment #15
cilefen CreditAttribution: cilefen at Institute for Advanced Study commentedBack to Entity Browser?
Comment #16
jds1Well, it's an Entity Embed issue if the alt text input should be happening at that last step before we hit the "Embed" button for a given image. If it's about the "Upload images as media items" form then that's probably Entity Browser (or whatever module controls that form).
For what it's worth, I'm working around this using Inline Entity Form and a custom form view mode that presents a short form/upload field. Doesn't support multi-uploads though. This really ought to be fixed either on that entity embed screen or in a step before we get to that screen.
Comment #17
emb03 CreditAttribution: emb03 commentedRE: comment #14 This is exactly my problem too.
Comment #18
samtny CreditAttribution: samtny at Digital Pulp commentedWe are experiencing this workflow problem also.
For now we will have to tell our clients to "be sure to click 'edit' so you can add alt text".
I may look at a quick form_alter hook to see if we can add a warning message when the (hidden) alt text is detected to be empty.
Comment #19
Wim LeersThe alternative text is already associated with/stored in the image managed by Media. Why do you need to be able to override it?
Comment #20
phenaproximaI can see the uses for this, for sure. It might have accessibility implications, too. The media item stores canonical alt text/title metadata, but that metadata might not make sense, or might otherwise lack some important context, when it's embedded in content. So I think that being able to override some metadata (alt text being the 80% use case, I'd hazard to guess) in a particular embed is quite useful. I believe Entity Embed already supports this, at least to some extent; I know that Lightning has code which will use the image embed display plugin by default when embedding an image media item, precisely to fulfill this case.
Comment #21
Wim LeersYou already allude to the tricky problem that this comes with: it only makes sense for images!
It doesn’t make sense for *all* media.
Or am I seeing that wrong? :)
Comment #22
jds1The issue here is not about how the alt text is associated with Media (specifically images), it's about how the image upload widget does not include a field for alt text. From my original post above:
I was able to get around this using an inline entity form, but I would expect the image upload widget to include this option.
I started writing this before Wim's latest comment, so yes this issue only makes sense for images! Agree!
Comment #23
Wim Leers@phenaproxima, do you understand how this relates to #2834112: [file entities] @EntityEmbedDisplay=image plugin's `alt` and `title` attributes not saving in CKEditor?
Comment #24
Wim Leers@if-jds: Also: thank you very much for your swift response! I hope we can bring this issue to a close in the near future.
Comment #25
phenaproximaAlthough the issue titles are similar, the actual problems are unrelated. That issue only refers to embedding file entities directly, whereas this is about embedding a media entity. The mechanisms for doing those two things are quite different, and the bug in the other issue is only affecting embedded files.
Comment #26
Wim LeersAha, so:
alt
andtitle
for images when using the@EntityEmbedDisplay=image
plugin and usingFile
entities. The only remaining problem there is that some configuration is not yet updated automatically.Media
entities.Is that a correct understanding?
Comment #27
phenaproximaThat is exactly right.
Comment #28
Wim LeersComment #29
jds1Thanks to all for your comments and contribution! Will love to see how this is done so I can learn more about the Media system backend =)
Comment #30
oknateFYI, in comment number #5, @if-jds is using Media Entity module and Media entity image. Media entity is now in core and includes an image bundle. To solve the issue, we should make sure it works for both the contrib module(s), used on older sites and the core version.
The sandbox module fixed the issue by using a new formatter based on Drupal\image\Plugin\Field\FieldFormatter\ImageFormatter.
Comment #31
oknateTesting this locally I found that if I select "Thumbnail" as the display option, it's using core MediaThumbnailFormatter and was giving (in Drupal 8.6) alt="thumbnail" in the output.
But that's because Thumbnail isn't really intended for display to the end user.
So that may be a fix for those who selected "Thumbnail" as the display in their test entity embed button.
It doesn't fix the workflow issue where you can't edit the alt text and title text within the form produced by EntityEmbedDialog. I think that's worth pursuing.
Comment #32
Wim LeersThat's what #2956368: MediaThumbnailFormatter produces unhelpful text alternative and title attributes for media thumbnails fixed indeed.
Yep, that's what this issue is about :)
Comment #33
oknateHere's a patch that adds access to the media image's alt and title fields within the dialog. Seems to work well with the view mode formatter.
It it seems like it wouldn't cause issues with any other embeds.
To do, it needs to be abstracted, so that we aren't hard coding the bundle and field name.
Comment #34
oknateHere's a slightly more generic variation on #33 that ignores the entity type and bundle and just checks if it has a file field at $entity->field_image.
This will work for core's media image as well as others that follow this pattern.
Comment #35
oknatethe patch above won't work on the standard profile because the standard profile's media image doesn't have field_image, it has field_media_image.
I think we'd need some sort of indication of which field to use, or else we'd just be guessing.
Also, I don't think this patch works with translation.
Comment #36
oknateredacted, was thinking we might need a new config or third party setting to specify the field, because I was ignorant of the media source plugin.
We can use that to determine if this is a media image and which field is the primary image field.
Comment #37
oknateOK, I see the above is unnecessary.
When you go to create one there's a form for setting the source field, so we can use that to determine the correct field.
Comment #38
oknateHere's a new patch based on #33 and #34 that uses the Source plugin to determine if it's an image and if it has a primary image field.
To do:
1) Alter the patch to make it work with translations of alt and title
2) add tests.
Comment #39
oknateI'm looking at editing the alt and title in the correct language based on the parent entity's language. But it looks like EntityEmbedDialog has no knowledge of the parent entity's language. Created a separate issue for that. #3018485: Selected Entity should display in host entity's language in EntityEmbedDialog when data-langcode not set
Comment #40
oknateAnother possible solution would be if we can get the correct translation from the selected entity's uuid. Is that possible?
Comment #41
oknateIt doesn't look like uuids are language specific, so that doesn't help. So I think we would need to pass the language code to the dialog to allow editing of the correct alt and title.
Comment #42
Wim LeersCorrect. Thanks for opening #3018485: Selected Entity should display in host entity's language in EntityEmbedDialog when data-langcode not set!
Comment #43
oknateI have a patch for #3018485: Selected Entity should display in host entity's language in EntityEmbedDialog when data-langcode not set that allows patch #38 to work with content translation.
Comment #44
oknatetitle field doesn't always exist on media image field_media_image field. Out of the box it isn't enabled:
So if we use the media image field's alt and title field as in patch 38, we'll need to account for that. Basically, we need to check if the field settings allow for it before displaying the form.
I tested it out when the title tag isn't enabled, and the code in patch 38 still manages to save the title property on field_media_image.
So that raises the question, should we ignore the default settings or hide the title field? I would think it should respect the field settings.
Comment #45
oknateAdding code to check if the title and alt field are disabled on the field settings, and if so, do not show in the entity embed dialog.
Comment #46
oknateI can also see the counterargument being made. What if you want to change the alt text on the original image each place it's used? Then it's no longer stored in one place. You'd have to find everywhere it's embedded and change it. I can understand wanting to change the caption, which is stored with the embed's drupal-entity data properties, but I think the alt and title should shouldn't be made data properties on the embed.
I could see another workflow where you use the media image field's alt and title as the defaults when embedding, but allow changing them, and once the embed is created, they are now decoupled from the original values. This would allow more granular control, but would also mean if you wanted to change the alt text on the original image, it wouldn't propagate to the embeds.
Comment #47
oknate- I think we could have a setting whether to use (to be added properties) data-image-alt and data-image-title properties.
- The administrator should be able to choose if they want the edit form to update the original alt/title.
- If the administrator chooses unique alt and title per embed, the alt and title could be saved on data-image-alt and data-image-title properties on the drupal-entity.
If we added all of this, it might be over-engineered, but everyone could be happy.
Comment #48
oknateOne issue with adding this functionality is that it isn't relevant for certain display plugins, such as label or entity id.
So if someone is using an entity embed based on a media entity and selects two display plugins, "label" and one derived from a view mode, it should really appear with ajax within the embed dialog if the user selects the view mode display. If you always display it for media image, then it would show up in the dialog when someone is embedding with the "label" formatter.
I guess that's not a real world situation. Most of the time, if someone's embedding an image, they'll use a view mode display plugin. So maybe it's best to always have it to keep the code simpler. They could always hide the fields with an alter hook.
Comment #49
oknateHere's a patch that addresses the issue mentioned in #48, that alt and title are irrelevant for "label" display plugins, et. al. This patch moves the code to the view mode formatter. This way, if you select "label" as well as a view mode display plugin, as you switch the select in the entity embed dialog, the alt text field goes away when you select label and returns when you select the view mode display.
Still to do:
- look into ImageFieldFormatter, which behaves differently. See if the functionality can be combined in some way.
- look into adding a checkbox or select to change the behavior so that if they want to save the alt and title per embed, rather than back to the image field on the media, user has an option to do that.
- add test coverage.
Comment #50
oknateHere's a video file showing the alt text field showing only on the view mode formatters, patch #49.
Comment #51
oknateHmm. Patch #48 wouldn't add the option to other plugins other than the view mode. The current title of this ticket has this verbiage:
But it isn't relevant for many plugins, so I think the title of the ticket could be revised. Only plugins that actually display an image should have the option.
Comment #52
oknateOops. I was testing the change in #49 and found it wasn't saving. This is why we need test coverage.
Comment #53
oknatepatch 50 had the same problem, was diffing the wrong branch. This should fix it.
Comment #54
oknateI'm trying to test out the ImageFieldFormatter, and I ran into a bug which is preventing me from testing it. See #3022754: @EntityEmbedDisplay=image plugin: no image-specific warning displays when invalid image selected.
I figured it out. See the issue for more details. The behavior is confusing when the image isn't valid.
Comment #55
oknateI added a second issue related to ImageFieldFormatter: #3022768: Validate that `alt` and `title` are required attributes for `<drupal-entity>`, and ensure they're added by default.
You must manually add "alt" and "title" attributes to the allowed html tags in the editor, or else the alt and title won't save.
Comment #56
oknate- Borrows some of the behavior from ImageFieldFormatter, such as allowing double quotes to represent an empty alt, even if required.
- Adds a select field under the alt textfield that allows choosing if you want to update the original entity or save to the embed!
Still to do:
- needs feedback / review
- needs test coverage.
I looked into whether we should apply the concept of saving to the embed vs saving to the entity to the ImageFieldFormatter display, and I believe file entity's only have the file_managed table and it doesn't support alt and title properties. So unless that changes, the ImageFieldFormatter can't support saving to the entity.
Comment #57
oknateComment #58
oknateComment #59
oknateThis patch moves the functionality to a separate class MediaViewModeFieldFormatter that extends ViewModeFieldFormatter. This new class is used for view mode display plugins when the entity type is "media". Since alt and title text is irrelevant for most entities, this is better organized.
I also tested with caching turned on and added a fix for caching. When you use the alt and title attributes on the drupal-entity to override the entity values, the entity view mode render array needs to have a different cache key.
Comment #60
andrewmacpherson CreditAttribution: andrewmacpherson as a volunteer and at Annertech commentedTagging this, to remind myself to try this out soon. There's a lot of discussion about the how various options (or override policies?) should work, and I'm not sure I'll understand what you're building until I try using it.
I'm skeptical of the idea in #44-45, that the embedded entity's image should follow the same policy for alt text as the original imagefield. It might make more sense to set the policy on the place where it's being embedded, if that's feasible. I'll ponder that a bit more, in the context of ATAG.
I think it would be perfectly reasonable for a site builder to set up an image media type without enabling the alt text field at all. Often the point of a media library is just to have a central place to collect assets, without caring about what purpose they will serve as content of an actual webpage. A default/canonical alt text may not be worth collecting in the library - only the alt text in context matters. A publisher may prefer to govern accessible content with house style guides and reviews, rather than entity schemas.
Conversely, alt text may be required by a image media type, but that doesn't mean an image can't serve a purely decorative purpose when embedded on a particular page.
Comment #61
Wim Leers#44:
+1. You did that in #45, great!
#46:
That would still work if no override was specified in the EntityEmbedDialog: if no override is specified, no
alt
attribute is injected, which should result in the embedded entity'salt
attribute being used. Changing the "original" (i.e. the embedded entity) would result in that showing up everywhere wherealt
was not overridden.This is not how I think most Media Initiative people think about this.
#47: why
data-image-alt
anddata-image-title
and not justalt
andtitle
?#48: correct. We should only show these fields if they also will show up in the chosen entity embed display. I see #49 already did that 👍 Thanks for the video in #50!
#56:
This is cool … but I think this is dangerous to do; it can easily result in data loss. It's hard to communicate clearly to the end user. I'd like to remove this for usability reasons.
#60:
That's not feasible.
The only two choices are: A) respect the existing field settings (which is what #45 does), or B) always require
alt
andtitle
.I disagree. Every image needs some textual description. Otherwise searching the media library becomes impossible. Searching just by filename is a nightmare (
IMG_*.JPG
times five thousand, anyone? 😂). And … that's also what Drupal 8 core already does out of the box: look at/media/add/image
😊At the very least: the default in Drupal 8 does have
alt
enabled for image media, and such defaults are rarely changed.This is true. But … how often to content authors insert purely decorative content in a text editor? Content authors shouldn't be dealing with pure decoration, but with content. Purely decorative images in text editors is generally a bad practice. And in any case, there already is an opt-in way out for this: the same one as Drupal core's image dialog has: entering
""
as the alt text.So as far as I'm concerned, the primary thing that should change is the removal of the "Save to embed" functionality.
Comment #62
oknatefor #47, I think the reason I was thinking #data-image-alt and #data-image-title was to be consistent with the other properties. This isn't an img tag, so to distinguish the properties, I was thinking giving them names that match the other attributes, such as data-entity-id. It's not important to me what they're called. I don't have a strong preference. If you like alt and title, I can change it back.
Sounds good, I can take a look in the next week, if no one else wants to jump in. Given the crickets I've been hearing around here, I doubt it.
Comment #63
Wim LeersI think
alt
andtitle
are well-understood, well-defined and therefore appropriate. We're using them on a custom element, but it'll be instantly clear to anybody who seems them what their meaning is.I think you're right :( That'd be wonderful! 🥳
Comment #64
oknateI thought of another good reason to use alt and title: it's already set up that way, so it's more backwards compatible.
Comment #65
Wim Leers#64: 👍
FYI: I marked #3052239: [media entities] Prepopulate caption with Media field data as related to this: what this issue/patch does for the
alt
andtitle
attributes, that aims to do for thedata-caption
attribute. Let's keep that separate though, because it's more complicated.Comment #66
Wim LeersPatch review before you start working on this again, so that you can tackle it all in one go:
Can't we override
::getEntityFromContext()
rather than overriding::build()
? That'd mean less duplicated code AFAICT :)Rather than doing this, I think we should
unset($build['#cache'])
in\Drupal\entity_embed\EntityEmbedDisplay\FieldFormatterEntityEmbedDisplayBase::build()
? Because caching an embed doesn't really make sense anyway; it's being cached as part of the host entity anyway :)Also: how is it possible we've never encountered this caching problem before?! :O EDIT: oh well, apparently there's still a whole bunch of TODOs relating to this, dating back to years ago. I shouldn't have been surprised I guess.
AFAICT this should be impossible, so if it is happening anyway, this should throw an exception.
Comment #67
oknateHere's an updated patch. It drops the option to save to the entity, per #61. I still think saving to entity would be a great alternative workflow, and this is still an issue with some of the entity browser upload widgets. If someone uploads an image through one of these widgets, the alt and text won't have been set, so there's no path to add the alt text on the image field of the media entity in that case yet. But perhaps that should be handled separately in entity browser module.
Perhaps the media upload widget within the entity browser should have its own fields for adding alt and title within the selection phase of the entity embed dialog (and while within the entity browser upload widget), or it should signal to the entity embed dialog that those values need saving and a form alter hook (within the entity browser module) could be added to change the default behavior of the title and alt field added in this patch.
In response to #66.2. If you remove this:
and unset($build['#cache']) in FieldFormatterEntityEmbedDisplayBase::build(), it doesn't prevent the embed from getting cached, because it has a pre render hook EntityViewBuilder::build which adds back the cache tags.
Perhaps it could be done with changes to FieldFormatterEntityEmbedDisplayBase::build() You could pre-render the entity and then remove the cache tags within FieldFormatterEntityEmbedDisplayBase::build() but you might break someone's custom implementation where they alter the cache tags.
Unless we can think of a better way to do it, I think adding a cache key within MediaViewModeFieldFormatter::build is the way to go.
Also, I tried moving the alteration of the field's alt and title to getEntityFromContext, but it doesn't work, because the entity gets rebuilt. See ViewModeFieldFormatter::getFieldValue():
Here's the context of the code above:
The build of the embed pretty much must go through this process, in order to capture alter hooks to the field formatter output. Therefore the overriding of the image field's alt and title needs to happen after FieldFormatterEntityEmbedDisplayBase::build(), which is why an override with the extra code works.
I also added some code because of a bug I encountered:
Here's the code I added:
Looking at this code now, it looks like maybe I should have used "elseif", since the conditional statement above would mean that $entity_element['data-entity-embed-display-settings'] is not empty, so you could skip checking it again.
Comment #68
oknateHere's an interdiff for #59 to #67.
Comment #69
oknateAddressing
Comment #70
oknateComment #71
oknateComment #72
oknateComment #73
Wim LeersThis is IMHO a problem with the defaults for when originally uploading media: it should not be allowed to upload those without specifying
alt
for each. That's also the approach Drupal 8.7's Media Library has taken. Perhaps Entity Browser ought to follow core's lead there.Argh, you're right. I was gonna say
, but Entity Embed allows any view mode to be selected, so that won't work either. Nor willhook_ENTITY_TYPE_ID_builde_defaults_alter()
.Perhaps it's okay for us to cache these after all. But … just adding a
embed
part to the key still will yield incorrect results, because it assumes that there's only one variation ever: a single "embed" variation. But every host entity may specify a differentalt
override. Which is why I think it is far better to not cache embedded entities' representations separately at all.So I did some more digging, and AFAICT this should work.
Thoughts?
Comment #74
oknateInteresting. I hadn't thought of the edge case of embedding the same image with different alt text. Here's a test case with alt text of "cat 1". Testing with
It totally doesn't work, not with #69 nor with #73. Marking back to "Needs Work".
Comment #75
oknateYou were on the right track. You just needed to remove the 'embed' cache key too. This works now with caching turned on and the test case in #74 embedded in one node's body.
Comment #76
Wim LeersAh yes, I did make that change locally but hadn't included it in the patch 😁
I think the only thing that's missing is functional test coverage! :)
Comment #77
oknateI'll work on the test coverage this week.
Comment #78
Wim LeersThank you! 🙏 🥳
Comment #79
oknateI started working on test coverage for this, but I realized the current patch doesn't add the alt and title "Regardless of @EntityEmbedDisplay plugin", for example media/src/Plugin/Field/FieldFormatter/MediaThumbnailFormatter.php isn't affected. This is because the override I created only affects view mode derived display plugins, not field formatter derived plugins.
There are two derivers that ship with entity embed:
Comment #80
oknateHere's initial test coverage.
There were some bugs I found.
1) A typo in the field settings:
2) #79, we need to get this working for displays using FieldFormatterDeriver.php
3) I found with the view mode deriver, if the thumbnail is displayed in the view mode, rather than the image, the alt and title text do not get overridden. I don't know why yet.
There were a few things I got stuck on, such as the @todo item here:
We need to figure out what to clear after updating the FieldConfig, so that the changes are reflected in the dialog, so we don't have to clear everything.
One thing I noticed after posting this: There's an extraneous select on the first two lines here that should be removed:
Comment #81
oknateHere's an update, although it's still a work in progress, I just ran out of time tonight.
It fixes media/src/Plugin/Field/FieldFormatter/MediaThumbnailFormatter.php using a similar approach in the FieldFormatterDeriver that we used in the ViewModeDeriver:
Since there aren't entity types to check in the deriver as there were with the view mode deriver, this is going to be trickier, so I put in a hack (hard-coded media_thumbnail) for now. We need to find a solution either here or when the plugin is loaded to switch classes based on the entity type, or just include the media functionality in the base class and then remove the two classes MediaViewModeFieldFormatter and MediaReferenceFieldFormatter. Another idea would be to have entity specific loading, or plugin using a different class on createInstance in the plugin factory. The classes, if kept, have a lot of redundancy between them, so we'd want a solution for that.
For this:
I haven't tested, but I'm pretty sure, since I had to fix this for the MediaThumbnailFormatter, we have to just update the alt and title on the thumbnail as well:
I started to change getImageSourceField, and I realized it doesn't even need entity interface, it should be MediaInterface. I think that's left over from an earlier iteration of this. So this function needs revision.
Comment #82
oknateComment #83
phenaproximaI discussed this with @oknate in Slack. Thanks to his patient explanation, I think I understand the problem we're facing here, and I propose a couple of potential solutions.
It seems to me that the issue here is we're trying to detect, at discovery time, which plugins will be capable of handling "images", or anything which could potentially have alt/title text. That seems a bit fragile to me; Entity Embed is designed to be extensible, so there's no real way for us to detect all possible ones which could need the capability. At least, not in an elegant fashion.
So, I see two possible options here:
Thoughts?
Comment #84
Wim LeersI really like the gist that #83 proposes. 👍 Let's try to go that way :)
Two remarks about it:
$configuration['_entity_embed_image_decorator']
is necessary — if a decorator is indeed working transparently, then there should be no reason for particular decoratable things to opt in or out of it.::isEmbeddingAnImage()
sample code is talking about the MIME type and using that to determine whetheralt
andtitle
override form items should be offered. Perhaps that makes sense in a future step, but I think this should be solely focused onMedia
entities representing images, since only there do we know how to retrieve the storedalt
andtitle
, that we allow the user to override.And finally, the one thing that I did see in the Slack chat but not captured in #83 is that the problem that @oknate was running into in #81 with derivers is that the concrete entity is not available at plugin derivation time; the decorator solution that @phenaproxima proposes is executed at runtime, and at that point a concrete
EntityInterface
object is available for inspection, so the challenges @oknate was facing vanish.Comment #85
phenaproximaI'm not sure I agree with this. Although I do think it's an edge case, there could be plausible scenarios where a display plugin wants to handle an "alt textable" entity (i.e., something it considers to be an image), yet not expose the alt text and title controls to the author. In which case, it would want to opt out of the decorator.
That said, it is an edge case and I'd be fine deferring this opt-out stuff for later, until someone actually requests it.
Comment #86
Wim Leers@phenaproxima and I agreed in Slack that we'd prefer not adding
$configuration['_entity_embed_image_decorator']
because it's extra API surface that we need to document and maintain and support; we agree it's better to only add that when the need arises.So, I think we're all on the same page here :)
Comment #87
oknateHere's a proof of concept for the decorator. It works, at least within the confines of the MediaImageTest functional javascript test the patch adds.
I need to add additional test coverage for the field formatter plugins and I need to add method comments within the decorator class, do some cleanup.
I think there are risks where if someone calls a custom method on their EntityEmbedDisplay, the decorator will not have implemented it. It's too bad there's not a generic way to pass methods on to the decorated class.
There's also a lot of jenky code like this:
setContextValue() is in the EntityEmbedDisplayBase but not in EntityEmbedDisplayInterface.
There may be a few more methods we need to add. We need to look at all the EntityEmbedDisplay plugins we know about and implement all of the known methods.
It seems like a lot of unnecessary code, and perhaps we could find a different solution. But it does force every plugin to be considered a candidate for our alteration, so for now, it's the best known solution.
I do want to keep exploring other possibilities. I think there may be a less verbose way of doing this.
Comment #88
phenaproximaYeah, I noticed this when writing the gist. The answer is (and we could do this in another issue, and block this one on that one) to add ContextAwarePluginInterface to EntityEmbedDisplayInterface, and make EntityEmbedDisplayBase extend ContextAwarePluginBase. Entity Embed already assumes that stuff is there, but it never formally supported it by using the correct interfaces. This could even potentially block RC, in my opinion -- I'd like to get Wim's opinion, though.
Comment #89
Wim LeersThere's
__call()
:) Example:\Drupal\Core\Plugin\Discovery\InfoHookDecorator::__call()
.Comment #90
oknateCool I'll look into that. A magic method. Makes sense. That would let us remove some of the irrelevant methods.
Comment #91
oknateAdds remaining test coverage and cleans things up. I don't know of any remaining issues.
Comment #93
Wim LeersThe failing testbot disagrees with you :D
Comment #94
oknateHmm. I thought I checked the entity type before passing it to that method.
Comment #95
oknateHere's a fix.
Comment #96
oknateComment #97
Wim LeersThanks so much for all your work on this! 🙏 👏
This could land in a separate issue; this is a separate bug that merits separate test coverage.
We still need to hardcode knowledge about specific entity embed display plugins. Not ideal, but better than the status quo. I think this is acceptable.
OTOH, isn't this what
$configuration['_entity_embed_image_decorator']
is for? If we need a reject list like this hardcoded, I'd much prefer to use$configuration['_entity_embed_image_decorator']
instead, because that's at least a pattern that third party entity embed display plugins can adopt themselves, without needing to also get added to this reject list.Nit: At least these two dependencies are unnecessary, perhaps more.
Nit: s/dom/DOM/, s/drupal-entity//
Comment #98
oknateI created a separate issue for #97.1
#3058872: Entity Embed render array shouldn't cache separately from host field
I'll work on the other three comments, marking back to Needs work.
Comment #99
oknateComment #100
oknateComment #101
Wim Leers#99: FYI:
<ol start=2>
makes the first<li>
start at 2 :)This combined with what you wrote in #99 made me realize that it's wrong to use
$configuration['_entity_embed_image_decorator']
. What we want is to add an optional plugin annotation keysupports_image_alt_and_title
to\Drupal\entity_embed\Annotation\EntityEmbedDisplay
with a default value ofFALSE
, and then opt in just the (derived) plugins that support it. That means we'll only retain theif ($definition['…'])
check.Other than that, this is now looking close. Sorry it took us this long to get here :)
Comment #102
oknateUpdated. There were a few coding style changes too.
Comment #103
oknateCorrected interdiff.
Comment #104
Wim LeersI like this much more!
Supports per-embed alt and title overrides for media entities with an image source.
Happy to do this on commit.
Perhaps
supports_image_alt_and_title_override
would be more descriptive?This does not match what's in the annotation :)
Comment #105
oknateI like supports_image_alt_and_title_override, although it's not really an override as an addition.
Some options:
Comment #106
oknateComment #107
phenaproximaPartial review. I didn't get to the tests, but I found only nitpicks in the stuff I did read -- except for one major, but not commit-blocking, thing.
Should be 'Returns TRUE if value is set.'
Nit: This can be one line.
Nit: Is there any particular reason not to simply
unset($build[0]['#cache'])
?Nit: TRUE should be passed as the third argument to in_array().
Nit: Should use ===
Nit:
supports_image_alt_and_title = TRUE
should have a trailing comma.Nice idea!
Nit: There is a superfluous blank line here.
And here.
Supernit: There's an extra space before "See".
This should probably use ===
Not a big deal, but should '""' be a constant on this class?
Nit: Extra blank line!
Nit: Blank line.
This seems like it should be an if/elseif?
Same here?
Nit: Blank line.
Not commit blocking, but this is a bit faulty and inflexible. Rather than test the entity's declared entity type ID, just check if it implements Drupal\media\MediaInterface. And we shouldn't couple this to a specific source plugin class -- instead, we should retrieve the source field definition and determine if its item class is ImageItem. This means it will support core image fields and anything that derives from them. If this can't be fixed now, can we open a follow-up issue for this, and mention it in a @todo comment above this code?
If we do as I mentioned above and check the source field definition ($entity->getSource()->getSourceFieldDefinition()), we don't need this check. Checking configuration values of the source plugin directly is, ultimately, violating encapsulation and therefore more brittle than it ideally should be.
So overall, this method should look something like this:
Comment #108
oknateThank you for your careful review, @phenaproxima. Lots of helpful feedback.
Comment #110
oknateTest failure due to this error:
When I was cutting and pasting I failed to add the constant to this class too.
Comment #111
oknateCoding standard fixes.
Comment #112
Wim Leers#107.3: that'd make us lose cacheability too. We just don't want to trigger render caching for embeds. We don't want to lose cache tags, contexts and max-age.
#108.3: Right, thanks for reminding me of #3058872: Entity Embed render array shouldn't cache separately from host field. That's technically a blocker to this issue.
#110: rather than duplicating the constant, I think it should just use the same constant.
This should not be necessary since the default value for the annotation already is
FALSE
. Oh, but this is the (confusingly named, this is a pre-existing problem) deriver for\Drupal\entity_embed\Plugin\entity_embed\EntityEmbedDisplay\EntityReferenceFieldFormatter
, which does have it set toTRUE
. D'oh. Clarified the comment.Comment #113
Wim LeersLet's see if tests here pass without that change.
Comment #114
Wim LeersThat failed, thanks to the explicit test coverage that this patch was adding.
Instead of doing that here, let's bring #113's interdiff and this comment's interdiff to #3058872: Entity Embed render array shouldn't cache separately from host field. The interdiff in this comment basically does exactly what I suggested over at #3058872-7: Entity Embed render array shouldn't cache separately from host field we do for test coverage.
By managing issue scope, we also are indirectly managing test scope. The test coverage that this interdiff removes also happens to not match the description (and hence scope) of the test method it's in! By moving that to a separate test, this becomes a lot simpler. Also pretty important: it doesn't need to be a functional JS test!
Comment #116
Wim LeersFixed one remaining CS fail, #111 introduced it.
Fixed another CS Fail that I introduced in #114.
Comment #117
Wim LeersThe #60 by accessibility maintainer @andrewmacpherson (yay, thanks for being present here!).
was added inI wrote in #61:
But that was wrong.
There is only one choice:
. Because Entity Embed reuses the existing entity view modes/displays, and those can only display fields that are actually present in a particular entity.This is working, and now even has explicit test coverage 🥳
Given that, removing
.Besides, this module is currently in beta, and has been for years. And this is definitely a step forward, because right now, you can only provide
alt
andtitle
by manually modifying the HTML! We'll do an RC before tagging a stable release, at that point it'll be great to have a round of accessibility review :)Comment #118
Wim LeersBefore committing, I wanted to test this manually. Unsurprisingly, it works great :)
We're far beyond 100 comments. This is a huge step forward. I think @phenaproxima still wanted to review the tests, and they can probably be improved just like any test can be improved, but it's testing the obvious edge cases already. Let's get anything else that we believe could and should be done better in a separate issue.
Thanks @oknate for being the driving force on this!
Comment #119
Wim LeersI don't know why this was not marked critical, because it is! That's why it was listed in #2577891: Entity Embed 8.x-1.0.0-rc1 release, because being able to create accessible content is critical.
🚢
Comment #120
Wim LeersNow see you in #3058872: Entity Embed render array shouldn't cache separately from host field for sure and perhaps also #3052239: [media entities] Prepopulate caption with Media field data!
Comment #122
Wim LeersARGH WTF! I've marked @oknate as the primary author on d.o, but it apparently reset that, now I've credited myself instead of @oknate 😩
Very sorry, @oknate, I'll credit the next patch that I'm the primary author of to you.
Comment #123
oknateNo worries. Thanks for hard work on this this morning, and getting it committed!
Comment #124
jds1This is amazing. Thank you @oknate and all who contributed to the resolution of this issue!