Problem/Motivation

@Wim Leers introduced \Drupal\ckeditor5\AdminUi::getSubmittedEditorAndFilterFormat in #3200008: Validation and editor settings. Ever since then, it's grown into a complex beast.

That, plus other unholy things:

  1. _ckeditor5_editor_form_filter_admin_format_validate() clears form errors in some scenarios
  2. using $form_state->getUserInput() instead of $form_state->getValues() in many places
  3. duplicate processing of form values — both within the same request, but also in different pieces of code

These are SEVERE risks for the CKEditor 5 module and Drupal core.

Thanks to refactoring and architectural improvements over the past two months, we can get rid of this, we can drastically simplify this. In particular thanks to #3228477: CKEditor5PluginConfigurableInterface should extend PluginFormInterface and ConfigurableInterface instead of adding ::settingsForm(), this is ready for significant simplification and refactoring.

Steps to reproduce

Proposed resolution

  1. Try to get rid of the AdminUi class altogether.
  2. Simplify!!!

Remaining tasks

User interface changes

API changes

Data model changes

CommentFileSizeAuthor
#13 3218985-13.patch2.05 KBWim Leers
#7 3218985-reproduce-bug.txt769 bytesWim Leers

Issue fork ckeditor5-3218985

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

bnjmnm created an issue. See original summary.

bnjmnm’s picture

bnjmnm’s picture

Title: [PP-1] Does AJAX validation need to happen when switching away from CK5? » Does AJAX validation need to happen when switching away from CK5?
Status: Postponed » Active
Wim Leers’s picture

I was testing this with:

diff --git a/core/modules/editor/editor.module b/core/modules/editor/editor.module
index 2dd2ed9760..ac3708b36f 100644
--- a/core/modules/editor/editor.module
+++ b/core/modules/editor/editor.module
@@ -222,6 +222,9 @@ function editor_form_filter_admin_format_validate($form, FormStateInterface $for
     $editor_plugin->validateConfigurationForm($form['editor']['settings']['subform'], $subform_state);
   }
 
+  $form_state->setErrorByName('filters', 'filters general');
+  $form_state->setErrorByName('filters[filter_html][settings][allowed_html]', 'filters specific');
+
   // This validate handler is not applicable when using the 'Configure' button.
   if ($form_state->getTriggeringElement()['#name'] === 'editor_configure') {
     return;

Wim Leers’s picture

Wim Leers’s picture

#3219076: When switching from CKEditor 4 to 5, the allowed HTML tags are not yet immediately auto-computed was clearly misguided, sorry for the noise.

I was tryint to get to the point where we only run this validation logic if and only if the resulting selected text editor plugin is CKEditor 5, at which point all of this can indeed just be removed.

Wim Leers’s picture

FileSize
769 bytes

I can confirm this is still a problem after #3201637: Figure out how to prevent data loss during upgrade/migration path. Patch attached to make testing this simpler.

Wim Leers’s picture

Title: Does AJAX validation need to happen when switching away from CK5? » AJAX validation should not happen when switching away from CKE5
Category: Task » Bug report
Issue tags: +stable blocker

I think this is the consensus.

Wim Leers’s picture

Assigned: Unassigned » bnjmnm
Status: Active » Postponed (maintainer needs more info)
Issue tags: +Needs steps to reproduce

Actually, I'm struggling to reproduce this now? 😅

Wim Leers’s picture

Seems like this is a related @todo:

function ckeditor5_form_filter_admin_format_validate(array $form, FormStateInterface $form_state) {
  // @todo do we need to run after editor_form_filter_admin_format_validate()?
bnjmnm’s picture

I'm not surprised this is no longer reproducible as we've made significant changes to the validation process, but it would be good to have a conclusive explanation. Here's something to start with, at least:
In #3201637: Figure out how to prevent data loss during upgrade/migration path, the types of validation checks specifically mentioned in the issue summary were moved to validation constraints. These constraints are checked in two places:

  • In ckeditor.moduleWhen switching to CKEditor 5 from a different (or null) editor. The validators won't fire when switching from CKEditor 5 to a different option.
  • From \Drupal\ckeditor5\Plugin\Editor\CKEditor5::validateConfigurationForm, so it would only be called when the CKEditor 5 config form is built

In other words, these validators are not really part of the text format form anymore aside from the specific use case of switching to.

I'll dig further as I'd like the evidence to be definitive before closing, but this covers a good chunk I believe.

Wim Leers’s picture

Status: Postponed (maintainer needs more info) » Needs work

Great, thanks for digging deeper! Marking "needs work" since it's not fully done yet, but well on its way obviously :)

Wim Leers’s picture

Assigned: bnjmnm » Wim Leers
Status: Needs work » Needs review
FileSize
2.05 KB

In digging into this, I actually think that we might be able to get rid of most AJAX complexity? 🤞

Status: Needs review » Needs work

The last submitted patch, 13: 3218985-13.patch, failed testing. View results

Wim Leers’s picture

Alright, going from ccc6fb3b0e0c35338d1190dbb63875461e289ecc yesterday to 496045c0ad088cbfe7b55577686a5c0b2c662aff today, I at least got Drupal\Tests\ckeditor5\FunctionalJavascript\CKEditor5AllowedTagsTest from

EFEE....

to

..EE....

That's progress.

I still have no idea how c654ec7576cc3ccf7a2db8b74c208474c6a08a3b managed to increase the number of failures though, because nothing is calling it… :O

Wim Leers’s picture

From 496045c0ad088cbfe7b55577686a5c0b2c662aff to d62cf32ca703f53d706ce1fa3fd1752ee927fad3 makes CKEditor5Test go from

.EEEE.E   

to

..EEE.E 

but made CKEditor5AllowedTagsTest go from

..EE.... 

to

..EEE...

Argh! Making CKEditor5Test::testHeadingsPlugin() pass made CKEditor5AllowedTagsTest::testAllowedTags() fail. At least that's a useful hint!

Wim Leers’s picture

Paired with @lauriii. He cannot reproduce the failures locally! He also tested with PHP 8.0, but with SQLite instead of MySQL (should not make a difference) and a newer version of Chrome+chromedriver.

I just pushed a commit which adds strict config schema checking only when PHP assertions are enabled; that should help narrow it down. And that is also a net improvement to DX for CKEditor 5 contrib developers.

Wim Leers’s picture

Looks like that is triggering net new failures! That's great! Even if this does not get us to green, it helps tracking things down then 👍

But … I just realized that the PHP log entries that commit will generate will not show up, because this branch was started before #3228355: PHP warning when saving text format with CKE5: $form_state->getTriggeringElement() unexpectedly returning NULL — we need to merge in all 1.0.x changes before it'll start generating useful output. So … doing that next. 🤞

Wim Leers’s picture

I'm now 90% certain that this is indeed caused by strict config schema checking only running on DrupalCI somehow. In the past few commits, I added it explicitly to \Drupal\ckeditor5\Plugin\Editor\CKEditor5::validateConfigurationForm() and despite DrupalCI still only showing

RuntimeException: Unable to complete AJAX request.

… I can see that the exact same steps to reproduce are now locally resulting in AJAX responses like

 <em class="placeholder">AssertionError</em>: Schema errors: Array
 (
     [editor.editor.cke5:settings.plugins.ckeditor5_imageUpload] =&gt; missing schema
 )
  in <em class="placeholder">assert()</em> (line <em class="placeholder">482</em> of <em class="placeholder">/Users/wim.leers/Work/d8/modules/ckeditor5/src/Plugin/Editor/CKEditor5.php</em>).

(Fixed that one in 9e56f6712b2aeceb9e9928547c6b2eaae3ca5fb3.)

What's weird is that \Drupal\Tests\ckeditor5\FunctionalJavascript\CKEditor5TestBase::tearDown() which was added in #3228355: PHP warning when saving text format with CKE5: $form_state->getTriggeringElement() unexpectedly returning NULL should be causing this to be visible, but it's … just not. It seems that the tearDown() is perhaps not being called in the case of Functional JS tests failing early? Yet ::tearDown() is supposed to be called always… I could decorate $assert_session->assertWaitOnAjaxRequest(); in CKE5 tests just so we get better error response checking… using the same technique as I added in \Drupal\Tests\media\FunctionalJavascript\CKEditorIntegrationTest::getLastPreviewRequestTransferSize().

Wim Leers’s picture

What's weird is that \Drupal\Tests\ckeditor5\FunctionalJavascript\CKEditor5TestBase::tearDown() which was added in #3228355: PHP warning when saving text format with CKE5: $form_state->getTriggeringElement() unexpectedly returning NULL should be causing this to be visible, but it's … just not. It seems that the tearDown() is perhaps not being called in the case of Functional JS tests failing early? Yet ::tearDown() is supposed to be called always

Actually … I think I figured out why:

00:06:37.487 FATAL Drupal\Tests\ckeditor5\FunctionalJavascript\CKEditor5Test: test runner returned a non-zero error code (2).

This is because \Drupal\FunctionalJavascriptTests\JSWebAssert::assertWaitOnAjaxRequest() triggers a \RuntimeException that the test runner won't handle. So it instantly aborts the test, without running ::tearDown()!

Related core issue: #3061852: [META] Deprecate assertWaitOnAjaxRequest() and make the JsWebAssert::waitFor*() methods behave like real assertions. It's been that way since it was introduced in #2648956: Editing a view leaves old keys hanging, results in invalid schema.

Wim Leers’s picture

Wim Leers’s picture

The last remaining call to AdminUi::getSubmittedEditorAndFilterFormat() was happening in AdminUi::validateConditions(). In trying to figure out how to get rid of that, I noticed … that it never worked. It was lacking test coverage too. So … refactoring it into validation constraints over at #3231220: Follow-up for #3216244: AdminUi::validateConditions() does not work, convert to validation constraint.

That's another good catch prior to opening the core merge request! 🤞

Wim Leers’s picture

Title: AJAX validation should not happen when switching away from CKE5 » CKEditor 5 admin UI's AJAX logic and form alterations are too complex and brittle
Priority: Normal » Major
Issue summary: View changes
Issue tags: -Needs steps to reproduce
Related issues: +#3228477: CKEditor5PluginConfigurableInterface should extend PluginFormInterface and ConfigurableInterface instead of adding ::settingsForm(), +#3200008: Validation and editor settings

Retitling because this issue was rescoped.

Wim Leers’s picture

Wim Leers’s picture

Status: Needs work » Needs review
tim.plunkett’s picture

Reviewing

tim.plunkett’s picture

Assigned: Wim Leers » Unassigned
Status: Needs review » Fixed

This is still a very tricky bit of code, but it is much easier to follow the flow now, has helpful assert() calls, and it is well documented. Farewell AdminUi!
Merged!

Status: Fixed » Closed (fixed)

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