Problem/Motivation
There are two issues with entity_embed_filter_format_edit_form_validate() that are interrelated and must be addressed together:
- entity_embed_filter_format_edit_form_validate() should check if 'filter_html' is enabled before validating
- entity_embed_filter_format_edit_form_validate() should check if
<drupal-entity>has attributes
The second issue only appears once the first has been fixed.
entity_embed_filter_format_edit_form_validate() should check if 'filter_html' is enabled before validating
When validating a filter format's edit page, entity_embed_filter_format_edit_form_validate() fails to account for a scenario where 'filter_html' is disabled.
The validation function should not be concerned with HTML restrictions of a disabled filter. The result is that a site builder cannot save the filter format.
Steps to reproduce
- Create filter format
- Drag an entity embed button to toolbar
- Check 'Limit allowed HTML tags and correct faulty HTML'
- Check 'Display embedded entities'
- Save
- Reopen form
- Remove
<drupal-entity data-entity-type data-entity-uuid data-entity-embed-display data-entity-embed-display-settings data-align data-caption data-embed-button data-langcode alt title>from allowed tags - Uncheck 'Limit allowed HTML tags and correct faulty HTML'
- Save
- Observe the following error:
'The %embed button requires <drupal-entity> among the allowed HTML tags.'
entity_embed_filter_format_edit_form_validate() should check if <drupal-entity> has attributes
After addressing the first issue, we must then address the second issue. When validating a filter format's edit page, entity_embed_filter_format_edit_form_validate() fails to account for a scenario where 'filter_html' is enabled with <drupal-entity> allowed as an element with no allowed attributes.
If <drupal-entity> is allowed but with no attributes, then $allowed['drupal-entity'] will be false. As a result, array_keys($allowed['drupal-entity']) will return null. As a result, when $missing_attributes is generated using an array_diff on null, it returns null, which causes the validation to incorrectly pass.
@oknate - thanks for working through the two prior issues that were combined into this one.
Proposed resolution
Check if 'filter_html' filter is enabled before proceeding with validation.
Allow for a situation where <drupal-entity> has no allowed attributed so that validation then fails.
Remaining tasks
Submit patch
Update tests once initial review is complete
User interface changes
None.
API changes
None.
Data model changes
None.
Release notes snippet
None.
| Comment | File | Size | Author |
|---|---|---|---|
| #29 | Screen Shot 2019-06-12 at 6.58.01 AM.png | 153.68 KB | oknate |
| #28 | 3060749-28.patch | 14.97 KB | wannesdr |
| #28 | 3060749-28-interdiff.txt | 542 bytes | wannesdr |
Comments
Comment #2
chris burge commentedComment #3
chris burge commentedComment #4
chris burge commentedComment #5
oknateI'm still seeing 'The %embed button requires among the allowed HTML tags.' on step 10 with 'Limit allowed HTML tags and correct faulty HTML' unchecked.
I would expect to see no error related to filter_html when the option is unchecked.
Comment #6
oknatefilter_html->status is wrong!
I think the major issue here is this is a validation hook, and runs before the entity object is updated, but it's checking if the filter is enabled on the not-yet-updated filter plugin object. So it works intermittently when you're not changing the filter statuses! If you were resaving the form without changing filters and writing the validation code, you would have missed the bug.
Changing where we check if a filter is enabled to check on the form_state values works much better!
That explained why I was getting some very unexpected behavior when testing.
I wrote some test cases on #3060728: entity_embed_filter_format_edit_form_validate() should check if 'filter_html' is enabled before validating and #3060729: entity_embed_filter_format_edit_form_validate() should check if <drupal-entity> has attributes.
Comment #7
oknateHere's a first test case. This is failing, so the bug still needs work.
Comment #8
oknateAnother surprising find. The validation wasn't running when adding a filter format!
Here's a fix for the first test case. I will add additional test coverage for the validation, and I'd like to move the validation in ImageFieldFormatterTest into this class FormatsValidationTest. I don't know if we want to get the fix in first, or wait for the test coverage.
Comment #9
wannesdr@oknate I can confirm the patch works fine. I talked to Wim and he will take a look later, see if we can move this forward!
Comment #10
wim leers@Chris Burge: Great find! Thanks for the detailed explanation and patch! 👍👏
#6 + #8 Nicely spotted :)
#8: Let's create a separate issue for moving the test coverage out of
ImageFieldFormatterTestinto this new test. Let's also move the configuration UI test coverage in\Drupal\Tests\entity_embed\FunctionalJavascript\CKEditorIntegrationTest::testIntegration()into this new test in that same issue.FormatsValidationTesttoConfigurationUiTest.This is unused.
Unused.
These aren't necessary.
This is doing the same thing twice, and with an unnecessary wait. Simplified.
Nit: we don't use camelCase.
So … we're testing that this is NOT working. Okay. That's … confusing.
I did some digging. This is caused by a pre-existing core bug: #2763075: Adding new text format gives Uncaught TypeError: f.format_tags.split is not a function. Having this test coverage is therefore a useful way for us to know when this is fixed in Drupal core.
Comment #11
wim leersLet's add the test coverage first.
Because the current test coverage passes without the changes here; it's actually a test unrelated to the reported bug :) It is test coverage for the additional bug that #8 found.
This we can do in a next issue. Or here, if you prefer. But it's definitely lower priority
Comment #12
oknateI actually built the test case off of manual testing: https://www.drupal.org/project/entity_embed/issues/3060729#comment-13140560
Comment #13
oknateThanks for the copious feedback, Wim. I'll try to get it updated this morning.
Comment #14
oknateOh, I see you already made most of the changes. We just need to finish the test coverage.
Comment #15
oknateAdds dataprovider based test to test both adding and editing the form.
One important change:
We don't need to validate the allowed values if $entity_embed_enabled is FALSE.
Comment #17
oknateThere are some cs that need cleanup. I have to head in to work now, though.
Comment #18
chris burge commentedThe progress didn't stop when I went home from work. Thanks to everyone for taking up this issue so quickly!
Comment #19
wim leers@oknate When do you think you'll continue? Otherwise I have somebody with me here at Drupal Dev Days who could fix those coding standards violations and the patch feedback I have below :)
We're using
NULLandFALSE, but AFAICT they're treated the same.s/a few attributes/some required attributes
Data providers' method names cannot start with the prefix
test— if they do, they'll be executed as test methods :)These aren't strings but booleans.
This can currently be either a string or
FALSE, so the documentation isn't accurate.Nit: s/html/HTML/
Woah! :D I didn't know this was possible :D
Clever. But let's not make this rely on jQuery. Let's use native DOM APIs (
document.querySelectorAll()).Comment #20
wim leersComment #21
oknateGo ahead, I will be out of pocket for 10 hours
Comment #22
oknateHere's an update. My apologies to anyone in Cluj who was hoping to work on it today. Thanks for all of the feedback, Wim. Lots of good catches. I'm kicking myself I put some booleans as strings in the param descriptions.
Comment #23
wannesdrThanks oknate for the update, I just have some small items of feedback:
#1
In core all the dataprovider method names are prefixed like this: provider. Just to be more consistent with core.
#2: A more general one: All tests and dataProviders in core are grouped together, and the test function is placed first followed by the dataProvider just below it. So I would reorder them to be more consistent, like in core.
Comment #24
wannesdrComment #25
wannesdrAttached is a new patch with the renamed and moved dataproviders.
I also included 2 interdiffs, one for the renaming and one for the moving, just to make it more clear what happend.
Comment #26
wannesdrPatch now applies.
Comment #27
wim leersCan you change this to use
$format->id()? That's the only nitpick.Thanks so much to both of you! :)
Comment #28
wannesdrThere you go. Last nitpick fixed.
Thank you guys for the help and feedback!
Comment #29
oknateFor consistency, there are other places in the functional javascript tests where we're doing Editor::create() and hard coding the id. Should those be changed as well? Or to avoid unrelated changes, save that for another time?
Comment #30
wannesdrGood call oknate! I would move that to a different issue, at least in my opinion. Just to prevent this issue from containing cs changes in all tests of the entity embed module.
Comment #31
wim leersThis.
What was still missing was a failing test run for the test coverage added in #22. I did that locally, and … success 👍
This means the test coverage is indeed reproducing the bug in HEAD.
Comment #33
wim leersComment #34
oknateSweet! That's some pretty thorough coverage!
Comment #35
wim leersIndeed — thanks to all of you! And especially @wannesderoy and @oknate 🥳
Comment #36
rosinegrean commented