Problem/Motivation
I'm getting following PHP error when saving text format with CKEditor 5:
Warning: Trying to access array offset on value of type null in Drupal\ckeditor5\AdminUi::isSwitchingToCkeditor5() (line 137 of core/modules/ckeditor5/src/AdminUi.php).
Drupal\ckeditor5\AdminUi::isSwitchingToCkeditor5(Object) (Line: 62)
Drupal\ckeditor5\AdminUi::getSubmittedEditorAndFilterFormat(Object) (Line: 284)
Drupal\ckeditor5\Plugin\Editor\CKEditor5->buildConfigurationForm(Array, Object) (Line: 177)
editor_form_filter_format_form_alter(Array, Object, 'filter_format_edit_form') (Line: 539)
Drupal\Core\Extension\ModuleHandler->alter('form', Array, Object, 'filter_format_edit_form') (Line: 835)
Drupal\Core\Form\FormBuilder->prepareForm('filter_format_edit_form', Array, Object) (Line: 279)
Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 73)
Drupal\Core\Controller\FormController->getContentResult(Object, Object) (Line: 39)
Drupal\layout_builder\Controller\LayoutBuilderHtmlEntityFormController->getContentResult(Object, Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 578)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 158)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 80)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 34)
Drupal\form_test\StackMiddleware\FormTestMiddleware->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 49)
Asm89\Stack\Cors->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 50)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 708)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
require('/Users/lauri.eskola/Projects/drupal/index.php') (Line: 65)
Steps to reproduce
- Revert the workaround added in #3228477.
- Use PHP 8.0.
- Install Standard and the CKEditor 5 module.
- Create a text format, granting administrators access, and select CKE5 as the editor for the format.
- Save the text format.
- Edit the text format you just created.
- Click save again (no changes needed).
- The error will appear onscreen if the site is configured to show warnings and notices; otherwise, check watchdog and it will be there.
Proposed resolution
Remaining tasks
User interface changes
API changes
Data model changes
| Comment | File | Size | Author |
|---|---|---|---|
| #26 | 3228355-26.patch | 2.83 KB | wim leers |
| #26 | interdiff.txt | 733 bytes | wim leers |
| #24 | 3228355-24.patch | 2.12 KB | wim leers |
| #9 | 3228355-9.patch | 1.74 KB | wim leers |
| #9 | interdiff.txt | 1.62 KB | wim leers |
Comments
Comment #2
wim leersWhat about something like this?
Comment #4
wim leersMaybe this?
Otherwise, maybe something like
Comment #6
tim.plunkettI don't have specific steps yet, but the fix is clear:
$form_state->getTriggeringElement()can return array or NULL, and that needs to be taken into account here.Comment #7
xjmOf note: For whatever reason, I was able to reproduce this on PHP 8.0 but not on PHP 7.3. The STR are:
Lauri was using PHP 8.0 and others were not, which explained the issues reproducing it.
The fact that the behavior is different on PHP 7.3 versus 8.0 is why we were concerned that we might have stumbled onto some regression with the FormState API.
Comment #8
wim leersLooks like I’m almost at the point where I can catch PHP notices in functional JS tests.
This also looks like something that belongs in Drupal core… so once I get it working I’ll file a core issue 👍
Comment #9
wim leersComment #11
wim leersNICE! That is working 🥳🤓 — that does mean this merits a Drupal core issue… so tagging .
Now … let's figure out whether this is indeed a PHP 8-only problem. Queuing tests for PHP 7.3 & 7.4. I bet it's a problem starting with PHP 7.4.
Comment #12
tim.plunkettFunny, the 7.3 tests catch a different PHP notice:
if (!(bool) $editor->getImageUploadSettings()['status']) {causes
Notice: Undefined index: status in Drupal\ckeditor5\Plugin\CKEditor5PluginManager->isPluginDisabled():D
Comment #13
wim leersOh … hah :D That's indeed absolutely not what I expected :P
Comment #14
xjmI can't believe we don't have a better way to fail tests on notices and warnings. Like that seems fundamentally broken at a basic level. We shouldn't have to check watchdog (although the method is pretty cool as a workaround).
Comment #15
xjmAsked about this and got the following info from @larowlan:
Comment #16
tim.plunkettAlso this warning was interfering with debugging on #3228477: CKEditor5PluginConfigurableInterface should extend PluginFormInterface and ConfigurableInterface instead of adding ::settingsForm(), so I committed a temporary workaround (pointing to this issue) that got merged in that MR:
https://git.drupalcode.org/project/ckeditor5/-/commit/50852d5802f4e9f8af...
Comment #17
xjmComment #18
xjmComment #20
wim leers+1
Which is why I wrote in #8:
I'm 90% certain that this simply never worked for functional JS tests. It's based on the user agent that the relevant middleware gets registered —
\Drupal\Core\CoreServiceProvider::registerTest()does:… but when using functional JS tests,
drupal_valid_test_ua()never returnsTRUEbecauseonly runs when using
$this->drupalGet(…), not when the browser itself makes AJAX requests due to e.g. typing something or clicking something.That's my theory at least 🙈
Comment #21
wim leersTesting my theory: #3228956: PHP notices are not detected for headless browser-triggered requests in FunctionalJavascript tests.
Comment #22
wim leers@tim.plunkett already committed a work-around in https://git.drupalcode.org/project/ckeditor5/-/commit/50852d5802f4e9f8af....
That means that the only thing to do here now is to A) prevent regressions, B) figure out if this is actually a deeper bug in Drupal core. For B), I've opened #3228956: PHP notices are not detected for headless browser-triggered requests in FunctionalJavascript tests. Postponing on that now.
Comment #23
wim leersWill push this forward on Monday.
Comment #24
wim leersFully confirmed over at #3228956: PHP notices are not detected for headless browser-triggered requests in FunctionalJavascript tests.
Per #3228956-9: PHP notices are not detected for headless browser-triggered requests in FunctionalJavascript tests and #3228956-12: PHP notices are not detected for headless browser-triggered requests in FunctionalJavascript tests, it's not clear yet how we want to address this in Drupal core. We should not wait for that. Instead, we can adopt the solution that Thunder uses per #3228956-10: PHP notices are not detected for headless browser-triggered requests in FunctionalJavascript tests, which is effectively a cleaned up version of the hack I applied here :) And we can simplify what they did, because … we do not want anything logged by PHP.
Comment #26
wim leersNice, #24 failed on the PHP notice that @tim.plunkett mentioned in #12 — but now in PHP 8 :) Great!
@tim.plunkett already fixed the originally reported PHP notice in #3228477: CKEditor5PluginConfigurableInterface should extend PluginFormInterface and ConfigurableInterface instead of adding ::settingsForm() as he mentioned in #16.
If this comes back green, I'm going to go ahead and merge this.
This ensures we'll remove it when the core issue lands :)
Comment #28
wim leers