Problem/Motivation
See #3270831-17: Make the CKEditor 4 → 5 upgrade path work even when the CKEditor 4 module is removed. This affects the CKEditor 5 upgrade path in Drupal 10.
The CKEditor 5 module has all sorts of functionality that migrates CKEditor 4 config to CKEditor 5. Because CKEditor 4 will not be compatible with Drupal 10, this migrate functionality can't expect the CKEditor 4 module to be present - it can only work with stored config. Currently, determining if a CKEditor 4 plugin is enabled requires calling code that resides in the CKEditor4 module - and as a result will not be be in Drupal 10. As a result, the CKEditor 5 migration has no way of knowing if a CKEditor 4 module is enabled and will migrate (and enable) any CKEditor 4 plugin with config (whether or not it's enabled for that text format).
This could result in plugins unexpectedly being enabled. With our current limitations, this is the best option as it ensures no data loss, but it still introduces the risk of enabling an unwanted plugin. A solution to this would be to remove CKEditor 4 plugin config for plugins that are not enabled. If this is in a 9.5 update hook, the config will be properly "config-santitized" for any text formats migrating to CKEditor 5.
Steps to reproduce
Proposed resolution
Remaining tasks
User interface changes
API changes
Data model changes
Release notes snippet
Previously, plugin settings for all CKEditor plugins were stored in the editor configuration. This included disabled plugins.
To keep the editor configuration in a consistent state, plugin settings are now only stored for CKEditor plugins that are enabled. Stored editor configuration entities will be updated in this release to remove the disabled plugin data.
To ensure CKEditor data is upgraded to CKEditor 5 correctly, sites should update to this release prior to updating to Drupal 10.
Comment | File | Size | Author |
---|---|---|---|
#29 | 3291744-29.patch | 19.4 KB | catch |
#25 | interdiff.txt | 652 bytes | lauriii |
#25 | 3291744-35.patch | 19.57 KB | lauriii |
#22 | interdiff-whitespace-22.txt | 645 bytes | xjm |
#22 | cke-3291744-22.patch | 19.56 KB | xjm |
Comments
Comment #2
bnjmnmComment #3
catchIf this update is going to be a necessary pre-requisite to updating to ckeditor5, then we will need to do two things:
1. Backport the update to 9.4.x
2. Remove the update from 10.0.x and implement hook_update_last_removed() for it.
We'll then need to special case ckeditor5 in system_requirements() so that people trying to update from 9.4.0 or earlier see a message telling them their version of core is too old. We had to do the same thing for workspaces in 9.0.x
Crosslinking #3290810: Remove updates added prior to 9.4.0 (9.4.4 for ckeditor) and add 9.4.0 database dumps and #3290808: Remove workspaces special casing from system_requirements() and fix versions/docs.
If it's not a necessary prerequisite and just an improvement, we might not need to do the above - but it'd be good to decide either way.
Comment #4
Wim LeersSo this is a major bug in the CKEditor 4 module that we need to fix to ensure the CKEditor 4 → 5 upgrade path works as you'd expect.
Comment #5
Wim LeersI'll take a first stab at this in the next 24 hours.
Comment #6
xjmI think given:
...We do probably need to do this. We should also double-check whether there are other issues affecting the data model.
Comment #7
Wim LeersAs promised: a patch that implements this.
This reuses code being removed in #3270831: Make the CKEditor 4 → 5 upgrade path work even when the CKEditor 4 module is removed: the
_ckeditor_get_enabled_plugins()
function is 100% copied!Note that we need not only a post-update hook, we also need to update
\Drupal\ckeditor\Plugin\Editor\CKEditor::submitConfigurationForm()
, to ensure that interactions with the Text Editor config UI after the update do not revert things back to the previously broken state.This still needs test coverage. I won't have time to write that before I leave on vacation, so unassigning.
Comment #8
Wim LeersI think this needs 2 tests:
\Drupal\Tests\ckeditor\Functional\CKEditorAdminTest
will actually fail, which means that'll be the test we just want to update :)Comment #10
lauriiiThis should address the failing tests + #8.
Comment #11
bnjmnmComment #12
xjmThis will need a change record, and maybe a release note given that we'll probably be backporting it to 9.4.x when usually this would be a minor-only change.
Minor nit, but this code isn't actually enabling anything, right? It's just retrieving a list of plugins that have been considered enabled.
I'm guessing we're not checking for whether the Editor module is enabled because CKE4 can't be enabled without it?
What happens if Editor is installed and one tries to delete all the editor config? 🤔 I guess it'd be an empty foreach loop for the update hook, but if it's possible for a site to exist in such a state, the update hook should return early if there are no configured editors.
I had to look up how this works; ConfigEntityUpdater::update() is some magic. But at least it's pre-existing magic.
I think this is meant to say:
As far as I can see, we're missing explicit test coverage for the runtime behavior here. (The upgrade path is covered.) There's maybe implicit test coverage given the changes to some tests related to stylescombo, but an explicit test would probably be good? It might be just one additional assertion in
CKEditorAdminTest
plus an line comment.Comment #13
catchThe actual logic here should happen in a hook_entity_presave() implementation - that way any default configuration in modules or install profiles will get the same treatment.
For an example see ViewsConfigUpdater and views_view_presave() (especially in 9.4.x/9.5.x - a lot has been removed in 10.x).
The update then more or less just loads and saves the config entities.
Comment #14
lauriii#12.1: Clarified the comments 👍
#12.2: This indeed leads into an empty foreach loop – I don't think there's anything needed here.
#12.4: Indeed! Updated 👍
#12.5: We already basically have explicit test coverage for this in
\Drupal\Tests\ckeditor\Functional\CKEditorAdminTest::testExistingFormat
. It tests both; that plugin settings are not saved for disabled plugins and that plugin settings are saved for enabled plugins.#13: Of course 🤦♂️ I have done this before but I haven't done this in years and I had forgotten about this approach already.
Comment #15
lauriiiComment #16
lauriiiComment #17
catchLast question here is whether this should be removed in Drupal 10 along with the new update (assuming we do indeed remove it and force people to update to >= 9.4.2 before going to Drupal 10). Or in Drupal 11 on the chance that some bad ckeditor4 default configuration exists in a Drupal 10 module/install profile. This seems a bit more unlikely than other default config like views given everything should shift over to ckeditor5 anyway. But... if it does need to stay into Drupal 11 just in case, we should add a @todo to remove it then.
edit: realised this is a non-issue, because this code is in ckeditor(4) module, which will be removed from core in Drupal 10 anyway, and probably go unsupported end of 2023 when ckeditor4 does - i.e. long before we'd want to tidy up this code.
Comment #18
Abhijith S CreditAttribution: Abhijith S as a volunteer and at Zyxware Technologies commentedFixed custom command fail issue in patch #14.
Comment #20
xjmThis actually I think, if we land this before next week's patch window.
CR looks OK too. I added some more info to both it and the release note. Thanks @lauriii!
Interdiff in #14 looks good; however, the test fail in #18 also looks relevant to the issue here:
Comment #21
lauriiiThis should address the remaining test failures. Removed a test case that was explicitly testing invalid editor configuration addressed by this issue which is no longer testable at least in a straight forward way.
Comment #22
xjmFixing trailing whitespace. :)
Comment #23
xjmComment #24
bnjmnmWent through the entire code and spotted one thing.
On line 167 $enabled_plugins it treated as an indexed array and on 176 it is associative. The latter use is more consistent with the method this was taken from, but the former seems simpler overall and consistent with the docs. It may not even have an impact, but having 176 be
$enabled_plugins[] = $plugin_id
may spare us future confusion.***************
I also went through https://git.drupalcode.org/search to see if there were any examples of contrib assuming a CKEditor plugin would have settings regardless of enabled stats, since language and stylescombo currently have config by default. I did not see evidence of this, though I'll acknowledge I may have missed something due to this Gitlab searches having different syntax requirements than the .ru site I'd previously used.
Comment #25
lauriiiGood catch @bnjmnm! I kept the array as an associative array to remove duplicates from the list. It doesn't matter in practice but it's better that way.
Comment #26
xjmMissed the window today, so updating tag.
Comment #28
catchCommitted/pushed to 10.1.x, 10.0.x and 9.5.x, this needs a 9.4.x-specific patch due to conflicts in ckeditor.module.
Comment #29
catchTrivial re-roll so setting back to RTBC pending a green test run.
Comment #30
catchActually let's get a review so I can commit this if it's OK.
Comment #31
lauriiiDo we want to commit the post_update to a patch release? I was thinking that it should be committed only to the next minor.
Comment #32
catch@lauriii if it wasn't blocking the ckeditor5 update then usually yes, but see #3291744-17: Ensure Editor config entities using CKEditor 4 only store plugins settings for actually enabled plugins. If the ckeditor5 update relies on this having run, we need to make sure every site runs it before attempting to update to ckeditor5, which means before they update to 10.0.0 at the latest, which in turn means implementing hook_update_last_removed() in ckeditor module. We want to require that sites update to at least 9.4.x before going to 10.0.0, but not require 9.5.x, which means getting this into a patch release.
edit: also, if all the ckeditor5 blockers are committed to 9.4.x, then ckeditor5 will be effectively stable in 9.4.something, which could see more sites trying to update to it in 9.4.
Comment #33
lauriiiMakes sense! The reroll in #29 looks good. 👍
Comment #35
catchSince I only fixed a couple of trivial merge conflicts I think it's OK to commit the backport too, so committed/pushed to 9.4.x thanks!
Comment #36
xjmWe should also have a version of the release note snippet for D10 saying sites must update to 9.4.4 prior to updating to 10.0.0.
Comment #37
catch@xjm I'd assume we'd add that in #3290810: Remove updates added prior to 9.4.0 (9.4.4 for ckeditor) and add 9.4.0 database dumps instead? It's not the case yet.
Comment #39
Erykt CreditAttribution: Erykt as a volunteer commentedAfter upgrading from 9.4.3 to 9.4.4 or 9.4.5 I get the error below. If I (before update) empty the file "web\core\modules\ckeditor\ckeditor.post_update.php" there is no error after update.
The website encountered an unexpected error. Please try again later.
Comment #40
Wim Leers🥳
Published the CRs (https://www.drupal.org/node/3293540 and https://www.drupal.org/node/3295369).
Comment #41
tjtj CreditAttribution: tjtj commentedI ran into a problem updating core from 9.4.3 to 9.4.5 that I think is related to this.
rushupdb
---------- ----------------- ------------- ---------------------------------
Module Update ID Type Description
---------- ----------------- ------------- ---------------------------------
ckeditor omit_settings_f post-update Updates Text Editors using
or_disabled_plu CKEditor 4 to omit settings for
gins disabled plugins.
---------- ----------------- ------------- ---------------------------------
In ProcessBase.php line 171:
Unable to decode output into JSON: Syntax error
Error: Call to a member function filters() on null in Drupal\ckeditor\Plugin\CKEditorPlugin\DrupalImageCaption->isEnabled() (line 111 of
/home/me
Hoo/public_html/web/core/modules/ckeditor/src/Plugin/CKEditorPlugin/DrupalImageCaption.php).
This throws a php error:
Error: Call to a member function getConfigDependencyName() on null in
Drupal\editor\Entity\Editor->calculateDependencies() (line 110 of
/home/me/public_html/web/core/modules/editor/s
How do I fix this?