If a filter's settings form has form elements inside of a fieldset, an error condition seems to happen which (at least on my local dev machine) triggers an error which then triggers an infinite loop, or something near enough to one that I run out of memory and get served a WSOD.

I've attached an example module which will trigger this. Enable the module and add the filter it provides to a text format to trigger the error.

Here's relevant PHP logs:

[19-Nov-2014 11:59:33 US/Mountain] PHP Fatal error:  Allowed memory size of 536870912 bytes exhausted (tried to allocate 72 bytes) in /Users/Albright/Sites/d8.test/www/core/vendor/symfony/debug/Symfony/Component/Debug/Exception/FlattenException.php on line 228
[19-Nov-2014 11:59:33 US/Mountain] PHP Stack trace:
[19-Nov-2014 11:59:33 US/Mountain] PHP   1. {main}() /Users/Albright/Sites/d8.test/www/index.php:0
[19-Nov-2014 11:59:33 US/Mountain] PHP   2. Drupal\Core\DrupalKernel->handle() /Users/Albright/Sites/d8.test/www/index.php:22
[19-Nov-2014 11:59:33 US/Mountain] PHP   3. Stack\StackedHttpKernel->handle() /Users/Albright/Sites/d8.test/www/core/lib/Drupal/Core/DrupalKernel.php:569
[19-Nov-2014 11:59:33 US/Mountain] PHP   4. Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle() /Users/Albright/Sites/d8.test/www/core/vendor/stack/builder/src/Stack/StackedHttpKernel.php:23
[19-Nov-2014 11:59:33 US/Mountain] PHP   5. Drupal\Core\StackMiddleware\PageCache->handle() /Users/Albright/Sites/d8.test/www/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php:58
[19-Nov-2014 11:59:33 US/Mountain] PHP   6. Drupal\Core\StackMiddleware\KernelPreHandle->handle() /Users/Albright/Sites/d8.test/www/core/lib/Drupal/Core/StackMiddleware/PageCache.php:52
[19-Nov-2014 11:59:33 US/Mountain] PHP   7. Symfony\Component\HttpKernel\HttpKernel->handle() /Users/Albright/Sites/d8.test/www/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php:53
[19-Nov-2014 11:59:33 US/Mountain] PHP   8. Symfony\Component\HttpKernel\HttpKernel->handleException() /Users/Albright/Sites/d8.test/www/core/vendor/symfony/http-kernel/Symfony/Component/HttpKernel/HttpKernel.php:74
[19-Nov-2014 11:59:33 US/Mountain] PHP   9. Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch() /Users/Albright/Sites/d8.test/www/core/vendor/symfony/http-kernel/Symfony/Component/HttpKernel/HttpKernel.php:222
[19-Nov-2014 11:59:33 US/Mountain] PHP  10. Drupal\Core\EventSubscriber\HttpExceptionSubscriberBase->onException() /Users/Albright/Sites/d8.test/www/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php:116
[19-Nov-2014 11:59:33 US/Mountain] PHP  11. Symfony\Component\Debug\Exception\FlattenException::create() /Users/Albright/Sites/d8.test/www/core/lib/Drupal/Core/EventSubscriber/HttpExceptionSubscriberBase.php:91
[19-Nov-2014 11:59:33 US/Mountain] PHP  12. Symfony\Component\Debug\Exception\FlattenException->setTraceFromException() /Users/Albright/Sites/d8.test/www/core/vendor/symfony/debug/Symfony/Component/Debug/Exception/FlattenException.php:52
[19-Nov-2014 11:59:33 US/Mountain] PHP  13. Symfony\Component\Debug\Exception\FlattenException->setTrace() /Users/Albright/Sites/d8.test/www/core/vendor/symfony/debug/Symfony/Component/Debug/Exception/FlattenException.php:175
[19-Nov-2014 11:59:33 US/Mountain] PHP  14. Symfony\Component\Debug\Exception\FlattenException->flattenArgs() /Users/Albright/Sites/d8.test/www/core/vendor/symfony/debug/Symfony/Component/Debug/Exception/FlattenException.php:208
[19-Nov-2014 11:59:33 US/Mountain] PHP  15. Symfony\Component\Debug\Exception\FlattenException->flattenArgs() /Users/Albright/Sites/d8.test/www/core/vendor/symfony/debug/Symfony/Component/Debug/Exception/FlattenException.php:223
[19-Nov-2014 11:59:33 US/Mountain] PHP  16. Symfony\Component\Debug\Exception\FlattenException->flattenArgs() /Users/Albright/Sites/d8.test/www/core/vendor/symfony/debug/Symfony/Component/Debug/Exception/FlattenException.php:223
   [snip]
[19-Nov-2014 11:59:33 US/Mountain] PHP  25. Symfony\Component\Debug\Exception\FlattenException->flattenArgs() /Users/Albright/Sites/d8.test/www/core/vendor/symfony/debug/Symfony/Component/Debug/Exception/FlattenException.php:223

Interestingly, when I first noticed this issue while working with Pathologic earlier today, I saw this line before ones like those above, though I can no longer replicate getting this line to show up (possibly since I've updated Drupal core since then). It may be a clue, though; 'local_settings' was the key for the fieldset in my form definition, and 'protocol_style' is a field in the fieldset.

[19-Nov-2014 06:36:15 US/Mountain] Uncaught PHP Exception InvalidArgumentException: "The configuration property filters.filter_pathologic.settings.local_settings.protocol_style doesn't exist." at /Users/Albright/Sites/d8.test/www/core/lib/Drupal/Core/Config/Schema/Mapping.php line 66

I'm both too unfamiliar with D8/Symfony's guts and jetlagged to diagnose further what might be going on here at the moment, but hopefully it rings a bell for someone. If not I'll try to take a closer look at it later (perhaps over the weekend).

Comments

Garrett Albright’s picture

Issue summary: View changes
Garrett Albright’s picture

Status: Active » Needs review
StatusFileSize
new1.45 KB

I'm now not so sure that the problem was due to an infinite loop. Maybe it actually can complete, if you give it enough RAM… I set memory_limit to 2G, but still ran out of memory. At any rate, I was getting into the weeds debugging that, so I took another approach.

This patch will "flatten" values of the settings form before they're saved. Not 100% sure that this is the correct approach (please post your argument if you don't think so), but it fixes the bug while making things work more like they did in Drupal 7. It will allow Pathologic for Drupal 7 and Drupal 8 to have the same UI, at least.

Garrett Albright’s picture

StatusFileSize
new4.29 KB

And here's a less-buggy version of the test filter which demonstrates this bug if you enable it before the patch. (For some reason I wasn't able to attach two files to my previous post.)

Status: Needs review » Needs work

The last submitted patch, 2: 2378437-2_elements_in_fieldset_filter_settings_form.patch, failed testing.

Garrett Albright’s picture

StatusFileSize
new1.66 KB

Okay, let's try this approach, then.

Garrett Albright’s picture

Status: Needs work » Needs review
cilefen’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

I can't enable the test module.
Drupal\Component\Plugin\Exception\PluginNotFoundException: The "filter_fieldsets_example" plugin does not exist. in Drupal\Core\Plugin\DefaultPluginManager->doGetDefinition() (line 57 of /Library/WebServer/Documents/drupal8x/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryTrait.php).

+++ b/core/modules/filter/src/FilterFormatEditForm.php
@@ -33,9 +33,39 @@ public function form(array $form, FormStateInterface $form_state) {
+    // "Flatten" submitted settings

Must be a period after this.

This should have tests.

Garrett Albright’s picture

Well, splendid. Something must have broken recently, because now Pathologic causes the same error when enabled too.

I'll bisect around and see if I can find a cause.

Garrett Albright’s picture

Yep… Enabling modules which provide filters is currently broken in core.

Garrett Albright’s picture

(Tried to add a related issue, but it didn't take…? Trying again. It's https://www.drupal.org/node/2348925 BTW)

(EDIT: I give up. :( )

tien.xuan.vo’s picture

I got this error too, when I go to this path: /node/add/my-custom-content
I applied this patch, but it does not work, I think because I did not submit any form.

tien.xuan.vo’s picture

I think the real issue is: every times we throw an exception, this issue occur. To know what is the exception, we can set 'args' to array() in Symfony\Component\Debug\Exception\FlattenException::setTrace(). After fixing the exception, this issue gone away.

nicholasthompson’s picture

I can confirm that the above patch lets the filter settings form submit again...

nicholasthompson’s picture

Scratch that - this breaks things which need to be nested, like checkbox arrays...

nicholasthompson’s picture

Also this only seems to fix edit - I get the error on Add too...

nicholasthompson’s picture

In FilterFormatFormBase, I did this to the submit:

    echo 'presave';
    $format->save();
    echo 'postsave';

This produces:

presave
Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 64 bytes) in /Users/nthompson/Sites/d8/drupal-8.0.0-beta4/core/vendor/symfony/debug/Symfony/Component/Debug/Exception/FlattenException.php on line 216

So The bug seems to be inside the format saving...

nicholasthompson’s picture

Drupal/Core/Config/Config.php

in the save() method there is a section for casting the value... This seems to be where a failure happens:

      foreach ($this->data as $key => $value) {
        echo "casting $key to : "; var_dump($value);
        $this->data[$key] = $this->castValue($key, $value);
      }
      echo 'done';
casting uuid to : string(36) "8105978f-4ac7-4351-9e00-00144ecc281a"
casting langcode to : string(2) "en"
casting status to : bool(true)
casting dependencies to : array(1) {
  ["module"]=>
  array(2) {
    [0]=>
    string(6) "editor"
    [1]=>
    string(14) "path_corrector"
  }
}
casting name to : string(10) "Basic HTML"
casting format to : string(10) "basic_html"
casting weight to : int(0)
casting filters to : array(10) {
  ["filter_html"]=>
  array(5) {
    ["id"]=>
    string(11) "filter_html"
    ["provider"]=>
    string(6) "filter"
    ["status"]=>
    bool(true)
    ["weight"]=>
    int(-50)
    ["settings"]=>
    array(3) {
      ["allowed_html"]=>
      string(106) "    
 <ul> <ol> <li> <dl> <dt> <dd> <h4> <h5> <h6> <p> <span> <img>"
      ["filter_html_help"]=>
      int(0)
      ["filter_html_nofollow"]=>
      int(0)
    }
  }
  ["filter_align"]=>
  array(5) {
    ["id"]=>
    string(12) "filter_align"
    ["provider"]=>
    string(6) "filter"
    ["status"]=>
    bool(true)
    ["weight"]=>
    int(-49)
    ["settings"]=>
    array(0) {
    }
  }
  ["filter_caption"]=>
  array(5) {
    ["id"]=>
    string(14) "filter_caption"
    ["provider"]=>
    string(6) "filter"
    ["status"]=>
    bool(true)
    ["weight"]=>
    int(-48)
    ["settings"]=>
    array(0) {
    }
  }
  ["filter_html_image_secure"]=>
  array(5) {
    ["id"]=>
    string(24) "filter_html_image_secure"
    ["provider"]=>
    string(6) "filter"
    ["status"]=>
    bool(true)
    ["weight"]=>
    int(-47)
    ["settings"]=>
    array(0) {
    }
  }
  ["filter_htmlcorrector"]=>
  array(5) {
    ["id"]=>
    string(20) "filter_htmlcorrector"
    ["provider"]=>
    string(6) "filter"
    ["status"]=>
    bool(true)
    ["weight"]=>
    int(-46)
    ["settings"]=>
    array(0) {
    }
  }
  ["editor_file_reference"]=>
  array(5) {
    ["id"]=>
    string(21) "editor_file_reference"
    ["provider"]=>
    string(6) "editor"
    ["status"]=>
    bool(true)
    ["weight"]=>
    int(-45)
    ["settings"]=>
    array(0) {
    }
  }
  ["filter_url"]=>
  array(5) {
    ["id"]=>
    string(10) "filter_url"
    ["provider"]=>
    string(6) "filter"
    ["status"]=>
    bool(false)
    ["weight"]=>
    int(-41)
    ["settings"]=>
    array(1) {
      ["filter_url_length"]=>
      string(2) "72"
    }
  }
  ["path_corrector"]=>
  array(5) {
    ["id"]=>
    string(14) "path_corrector"
    ["provider"]=>
    string(14) "path_corrector"
    ["status"]=>
    bool(true)
    ["weight"]=>
    int(-44)
    ["settings"]=>
    array(2) {
      ["tags"]=>
      array(2) {
        ["a"]=>
        int(0)
        ["img"]=>
        int(0)
      }
      ["string_replacements"]=>
      string(23) "example.com|example.org"
    }
  }
  ["filter_autop"]=>
  array(5) {
    ["id"]=>
    string(12) "filter_autop"
    ["provider"]=>
    string(6) "filter"
    ["status"]=>
    bool(false)
    ["weight"]=>
    int(-42)
    ["settings"]=>
    array(0) {
    }
  }
  ["filter_html_escape"]=>
  array(5) {
    ["id"]=>
    string(18) "filter_html_escape"
    ["provider"]=>
    string(6) "filter"
    ["status"]=>
    bool(false)
    ["weight"]=>
    int(-43)
    ["settings"]=>
    array(0) {
    }
  }
}
</pre>

We never get a <code>done

....

nicholasthompson’s picture

Processing uuid... Done
Processing langcode... Done
Processing status... Done
Processing dependencies... Done
Processing name... Done
Processing format... Done
Processing weight... Done
Processing filters... 
Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 72 bytes) in /Users/nthompson/Sites/d8/drupal-8.0.0-beta4/core/vendor/symfony/debug/Symfony/Component/Debug/Exception/FlattenException.php on line 221
nicholasthompson’s picture

It seems to be inside the "castValue" method in StorableConfigBase...

...
...
filters.filter_url.settings
string(6) "object"
filters.filter_url.settings.filter_url_length
string(6) "object"
filters.path_corrector
string(6) "object"
filters.path_corrector.id
string(6) "object"
filters.path_corrector.provider
string(6) "object"
filters.path_corrector.status
string(6) "object"
filters.path_corrector.weight
string(6) "object"
filters.path_corrector.settings
string(6) "object"
filters.path_corrector.settings.tags
string(6) "object"
filters.path_corrector.settings.tags.a

Seems to be dying when trying to get the element for the "a" checkbox in my modules form...

nicholasthompson’s picture

So all my debugging has led me back to Mapping.php as Garret has found originally.

In my case, the final item filters.path_corrector.settings.tags.a produces a NULL $element....

nicholasthompson’s picture

If I debug the class of $element at each step, then var_dump the element if there is no "get" method... I get this:

KEY: uuid 
KEY: langcode 
KEY: status 
KEY: dependencies 
KEY: dependencies.module 
Drupal\Core\Config\Schema\Mapping
KEY: dependencies.module.0 
Drupal\Core\Config\Schema\Mapping
Drupal\Core\Config\Schema\Sequence
KEY: dependencies.module.1 
Drupal\Core\Config\Schema\Mapping
Drupal\Core\Config\Schema\Sequence
KEY: name 
KEY: format 
KEY: weight 
KEY: filters 
KEY: filters.filter_html 
Drupal\Core\Config\Schema\Sequence
KEY: filters.filter_html.id 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_html.provider 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_html.status 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_html.weight 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_html.settings 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_html.settings.allowed_html 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_html.settings.filter_html_help 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_html.settings.filter_html_nofollow 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_align 
Drupal\Core\Config\Schema\Sequence
KEY: filters.filter_align.id 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_align.provider 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_align.status 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_align.weight 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_align.settings 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_caption 
Drupal\Core\Config\Schema\Sequence
KEY: filters.filter_caption.id 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_caption.provider 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_caption.status 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_caption.weight 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_caption.settings 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_html_image_secure 
Drupal\Core\Config\Schema\Sequence
KEY: filters.filter_html_image_secure.id 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_html_image_secure.provider 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_html_image_secure.status 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_html_image_secure.weight 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_html_image_secure.settings 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_htmlcorrector 
Drupal\Core\Config\Schema\Sequence
KEY: filters.filter_htmlcorrector.id 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_htmlcorrector.provider 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_htmlcorrector.status 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_htmlcorrector.weight 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_htmlcorrector.settings 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.editor_file_reference 
Drupal\Core\Config\Schema\Sequence
KEY: filters.editor_file_reference.id 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.editor_file_reference.provider 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.editor_file_reference.status 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.editor_file_reference.weight 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.editor_file_reference.settings 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_url 
Drupal\Core\Config\Schema\Sequence
KEY: filters.filter_url.id 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_url.provider 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_url.status 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_url.weight 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_url.settings 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.filter_url.settings.filter_url_length 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
Drupal\Core\Config\Schema\Mapping
KEY: filters.path_corrector 
Drupal\Core\Config\Schema\Sequence
KEY: filters.path_corrector.id 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.path_corrector.provider 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.path_corrector.status 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.path_corrector.weight 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.path_corrector.settings 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
KEY: filters.path_corrector.settings.tags 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
Drupal\Core\Config\Schema\Sequence
KEY: filters.path_corrector.settings.tags.a 
Drupal\Core\Config\Schema\Sequence
Drupal\Core\Config\Schema\Mapping
Drupal\Core\Config\Schema\Sequence
object(Drupal\Core\TypedData\Plugin\DataType\String)#811 (5) {
  ["value":protected]=>
  array(2) {
    ["a"]=>
    int(0)
    ["img"]=>
    int(0)
  }
  ["definition":protected]=>
  object(Drupal\Core\TypedData\DataDefinition)#810 (1) {
    ["definition":protected]=>
    array(4) {
      ["type"]=>
      string(6) "string"
      ["label"]=>
      string(5) "Value"
      ["class"]=>
      string(45) "\Drupal\Core\TypedData\Plugin\DataType\String"
      ["definition_class"]=>
      string(37) "\Drupal\Core\TypedData\DataDefinition"
    }
  }
  ["name":protected]=>
  string(4) "tags"

So, for some reason, it's interpreting my "tags" array as a string?!

nicholasthompson’s picture

Ahh... I have a feeling this might be a "feature"...

https://api.drupal.org/api/drupal/core%21modules%21filter%21src%21Plugin...

It looks like FilterFormat's expect all settings to be strings. There doesn't seem to be anything in there to consider a filter format setting data type to be anything other that string.

EDIT: I got to this by looking in TypedConfigManager.php and when it gets a definition of a fomat, we see:

Array
(
    [type] => filter
    [label] => Filter
    [class] => \Drupal\Core\Config\Schema\Mapping
    [definition_class] => \Drupal\Core\TypedData\MapDataDefinition
    [mapping] => Array
        (
            [id] => Array
                (
                    [type] => string
                    [label] => ID
                )

            [provider] => Array
                (
                    [type] => string
                    [label] => Provider
                )

            [status] => Array
                (
                    [type] => boolean
                    [label] => Status
                )

            [weight] => Array
                (
                    [type] => integer
                    [label] => Weight
                )

            [settings] => Array
                (
                    [type] => filter_settings.[%parent.id]
                )

        )

)
nicholasthompson’s picture

Ahhh - I wonder if we need to define a schema for our format settings?!

https://api.drupal.org/api/drupal/core!modules!filter!config!schema!filt...

nicholasthompson’s picture

Ah ha!!! This is not a Drupal 8 bug - this is a documentation issue IMHO ;)

Filter Settings are (I believe) assumed to be Strings, unless you specify otherwise.

I have fixed this on Path Corrector by adding this to config/schema/path_corrector.schema.yml:

filter_settings.path_corrector:
  type: filter
  label: 'Path Corrector'
  mapping:
    tags:
      type: sequence:
      label: 'Tags'
      sequence:
        type: string
        label: 'Tag'
    string_replacements:
      type: string
      label: 'String Replacements'

My clue was when I saw filter_settings.[%parent.id] above... I ended up finding /core/modules/filter/config/schema/filter.schema.yml and saw that Filter HTML and Filter URL all define their own config schema.

Arguably, Drupal should handle this error better. Some kind of "incompatible DataType" or something - without a full on WSOD...

EDIT: This is pretty handy - https://www.drupal.org/node/1905070

Garrett Albright’s picture

Do you think you could share what your form that goes along with those settings looks like?

I added a .schema.yml file and now I see the general Drupal error page upon saving instead of the WSOD, but the error in the watchdog seems to imply it's still trying to save settings at another level "down" with the name of the fieldset. Do I really have to replicate my form structure in the structure of my schema?

nicholasthompson’s picture

I'm on my phone right now so can't get to the code easily... But checkout the Drupal 8 branch of Path Corrector.

TLDR is "yes" - you need to replicate quite a bit. In my case with the checkboxes I had to define that the checkboxes were a mapping and that each child would be a string.

nicholasthompson’s picture

Garrett Albright’s picture

I was looking for the form that corresponds to the schema, not the schema itself. I guess this is it: http://cgit.drupalcode.org/path_corrector/tree/src/Plugin/Filter/FilterP...

But it looks like your form isn't using fieldsets after all, so perhaps we were talking past each other…

Garrett Albright’s picture

Title: Field elements in fieldsets on filter settings cause infinite error loop/WSOD when saved » How to put field elements in fieldsets in filter config forms
Status: Needs work » Closed (works as designed)
Issue tags: -Needs tests
StatusFileSize
new9.04 KB

Okay. After some experimentation, I've gotten things to work.

The keys are, one, you *do* need to replicate the structure of the form in the schema (argh), and two, you also need to do so in the "settings" part of the filter annotation. In $this->settings, the field values will be in sub-arrays also corresponding to everything.

I've attached an updated version of the example module I posted in the OP which works. Check out the 8.x-1.x branch of Pathologic for a more complex example.