Problem/Motivation

Editor plugins all implement PluginFormInterface, which is used for subforms. Their plugin configuration forms are always contained by a parent form.
Currently they are explicitly tied to the form structure defined by editor_form_filter_format_form_alter().

Proposed resolution

#2537732: PluginFormInterface must have access to the complete $form_state (introduce SubFormState for embedded forms) introduced the concept of SubformState, for partial forms that are built as part of a larger form.
Editor plugins should utilize this to remove the coupling to the parent form structure.

Remaining tasks

User interface changes

N/A

API changes

API addition. Editor forms directly implementing the PluginFormInterface methods (instead of the deprecated settingsForm* methods) will be passed a SubformState instance.

Data model changes

N/A

Comments

tim.plunkett created an issue. See original summary.

tim.plunkett’s picture

This is independent of #2326721: EditorPluginInterface should extend PluginFormInterface, but the patches will conflict, so probably best to wait on that.

wim leers’s picture

Title: Editor plugins should be passed SubformState » [PP-1] Editor plugins should be passed SubformState
Status: Active » Postponed
Related issues: +#2326721: EditorPluginInterface should extend PluginFormInterface

+1!

wim leers’s picture

Title: [PP-1] Editor plugins should be passed SubformState » Text Editor plugins should be passed SubformState
Status: Postponed » Active
tim.plunkett’s picture

Status: Active » Needs review
StatusFileSize
new2.76 KB

Do you think this needs tests to prove exactly WHY we need this change?

Status: Needs review » Needs work

The last submitted patch, 5: 2819731-editor-5.patch, failed testing.

tim.plunkett’s picture

Hmm, that switch was fine for block plugins, because they were already doing the correct form_state manipulate to only pass the appropriate values along.
My guess (without actually looking at editor plugins) is that all of their $form_state->getValue calls were relative to the editor form itself, and not just it's own form valudes

wim leers’s picture

My guess (without actually looking at editor plugins) is that all of their $form_state->getValue calls were relative to the editor form itself, and not just it's own form valudes

This is true. See \Drupal\ckeditor\Plugin\Editor\CKEditor::settingsFormSubmit():

  public function settingsFormSubmit(array $form, FormStateInterface $form_state) {
    // Modify the toolbar settings by reference. The values in
    // $form_state->getValue(array('editor', 'settings')) will be saved directly
    // by editor_form_filter_admin_format_submit().
    $toolbar_settings = &$form_state->getValue(array('editor', 'settings', 'toolbar'));

    // The rows key is not built into the form structure, so decode the button
    // groups data into this new key and remove the button_groups key.
    $toolbar_settings['rows'] = json_decode($toolbar_settings['button_groups'], TRUE);
    unset($toolbar_settings['button_groups']);

    // Remove the plugin settings' vertical tabs state; no need to save that.
    if ($form_state->hasValue(array('editor', 'settings', 'plugins'))) {
      $form_state->unsetValue(array('editor', 'settings', 'plugin_settings'));
    }
  }

Does this mean we can't do this until D9? I think we can predict what catch will say about that :)

How about we do something like:

  1. Use reflection to detect whether the editor plugin itself implements the deprecated settingsFormSubmit(), or the new submitConfigurationForm().
  2. Let the calling code behave differently according to that.
tim.plunkett’s picture

Status: Needs work » Needs review
StatusFileSize
new3.3 KB
new6.06 KB

How about this?

wim leers’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/ckeditor/src/Plugin/Editor/CKEditor.php
    @@ -234,20 +234,15 @@ public function settingsForm(array $form, FormStateInterface $form_state, Editor
    -  public function settingsFormSubmit(array $form, FormStateInterface $form_state) {
    -    // Modify the toolbar settings by reference. The values in
    -    // $form_state->getValue(array('editor', 'settings')) will be saved directly
    -    // by editor_form_filter_admin_format_submit().
    -    $toolbar_settings = &$form_state->getValue(array('editor', 'settings', 'toolbar'));
    -
    +  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
         // The rows key is not built into the form structure, so decode the button
         // groups data into this new key and remove the button_groups key.
    -    $toolbar_settings['rows'] = json_decode($toolbar_settings['button_groups'], TRUE);
    -    unset($toolbar_settings['button_groups']);
    +    $form_state->setValue(['toolbar', 'rows'], json_decode($form_state->getValue(['toolbar', 'button_groups']), TRUE));
    +    $form_state->unsetValue(['toolbar', 'button_groups']);
     
         // Remove the plugin settings' vertical tabs state; no need to save that.
    -    if ($form_state->hasValue(array('editor', 'settings', 'plugins'))) {
    -      $form_state->unsetValue(array('editor', 'settings', 'plugin_settings'));
    +    if ($form_state->hasValue('plugins')) {
    +      $form_state->unsetValue('plugin_settings');
         }
       }
    

    I'd like to see this patch without these changes, because that would prove it doesn't break BC.

    Alternatively, make this change, but then we'll need to add test coverage for this, probably to \Drupal\Tests\editor\Unit\EditorBaseTest.

  2. +++ b/core/modules/editor/editor.module
    @@ -214,6 +215,11 @@ function editor_form_filter_admin_form_ajax($form, FormStateInterface $form_stat
    +  if ($editor_plugin = $form_state->get('editor_plugin')) {
    

    Isn't this always going to be true, because of line 175, which always does $form_state->set('editor_plugin', $plugin);?

tim.plunkett’s picture

Title: Text Editor plugins should be passed SubformState » Text Editor plugins are coupled to editor_form_filter_format_form_alter()
Category: Task » Bug report
Issue summary: View changes
Status: Needs work » Needs review
StatusFileSize
new9.15 KB
new7.5 KB
new3.09 KB
+++ b/core/modules/editor/editor.module
@@ -170,11 +171,11 @@ function editor_form_filter_format_form_alter(&$form, FormStateInterface $form_s
   if ($editor) {
...
+    $form_state->set('editor_plugin', $plugin);

Well, this is only set when $editor is truthy, so I thought it best to check.

Uploading a version without the CKEditor changes, but also a full patch with test coverage.

tim.plunkett’s picture

StatusFileSize
new9.17 KB
new3.12 KB

Wim pointed out that I should not change the existing coverage, just add more.

Interdiff is against #9

wim leers’s picture

Status: Needs review » Needs work
Issue tags: +Needs change record updates

Thanks! Very close to RTBC.

Just one small thing left:

+++ b/core/modules/editor/tests/src/Unit/EditorBaseTest.php
@@ -48,6 +49,47 @@ public function testBc() {
+    // settingsForm() is deprecated in favor of buildConfigurationForm().
...
+    // settingsFormValidate() is deprecated in favor of
+    // validateConfigurationForm().
...
+    // settingsFormSubmit() is deprecated in favor of submitConfigurationForm().

These comments are the same as the original ones.

They should say something like settingsForm() uses SubFormState and is deprecated in favor of buildConfigurationForm() which uses FormState, the BC layer ensures they are have the same results.

Repeat for all three.


This should also update the CR at https://www.drupal.org/node/2819753.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

tim.plunkett’s picture

StatusFileSize
new9.16 KB

Reroll. Did not address #13 yet.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

tim.plunkett’s picture

Status: Needs work » Needs review
StatusFileSize
new9.76 KB
wim leers’s picture

Status: Needs review » Reviewed & tested by the community
StatusFileSize
new1.99 KB
new10.06 KB

🥳 Thanks, Tim! 🙏

Addressed my own nits in #13.

larowlan’s picture

Status: Reviewed & tested by the community » Fixed
+++ b/core/modules/editor/src/Plugin/EditorBase.php
@@ -34,6 +35,9 @@ public function getDefaultSettings() {
+      if ($form_state instanceof SubformStateInterface) {
+        $form_state = $form_state->getCompleteFormState();
+      }

😎

Committed ef01478 and pushed to 8.8.x. Thanks!

  • larowlan committed ef01478 on 8.8.x
    Issue #2819731 by tim.plunkett, Wim Leers: Text Editor plugins are...
larowlan’s picture

Can we get those change record updates please (or the tag removed).

Thanks!

Status: Fixed » Closed (fixed)

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