(I did not find this issue reported yet when searching. I apologize if this is a double report.)
I have created a module that defines a custom content entity type. The module code only defines a Title field and hidden fields.
Via the Drupal interface, I added a field named "Category" to this entity type. The Category field is a text list field that only accepts 1 choice ("select" widget).
In /admin/structure/views/, I attempt to create a new Page view to only retrieve instances of this entity that have a certain Category value.
Because one of the Category choices selected for this view contains a period ".", Drupal crashes and displays the following in an otherwise blank page:
The website encountered an unexpected error. Please try again later.
Drupal\Core\Config\ConfigValueException: Dr. BPP key contains a dot which is not supported. in Drupal\Core\Config\ConfigBase->validateKeys() (line 211 of core\lib\Drupal\Core\Config\ConfigBase.php).
Drupal\Core\Config\ConfigBase->validateKeys(Array) (Line: 214)
Drupal\Core\Config\ConfigBase->validateKeys(Array) (Line: 214)
Drupal\Core\Config\ConfigBase->validateKeys(Array) (Line: 214)
Drupal\Core\Config\ConfigBase->validateKeys(Array) (Line: 214)
Drupal\Core\Config\ConfigBase->validateKeys(Array) (Line: 214)
Drupal\Core\Config\ConfigBase->validateKeys(Array) (Line: 161)
Drupal\Core\Config\ConfigBase->setData(Array) (Line: 107)
Drupal\Core\Config\Config->setData(Array) (Line: 279)
Drupal\Core\Config\Entity\ConfigEntityStorage->doSave('protein', Object) (Line: 392)
Drupal\Core\Entity\EntityStorageBase->save(Object) (Line: 259)
Drupal\Core\Config\Entity\ConfigEntityStorage->save(Object) (Line: 358)
Drupal\Core\Entity\Entity->save() (Line: 637)
Drupal\Core\Config\Entity\ConfigEntityBase->save() (Line: 986)
Drupal\views_ui\ViewUI->save() (Line: 312)
Drupal\views_ui\ViewEditForm->save(Array, Object)
call_user_func_array(Array, Array) (Line: 111)
Drupal\Core\Form\FormSubmitter->executeSubmitHandlers(Array, Object) (Line: 51)
Drupal\Core\Form\FormSubmitter->doSubmitForm(Array, Object) (Line: 583)
Drupal\Core\Form\FormBuilder->processForm('view_edit_form', Array, Object) (Line: 314)
Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 48)
Drupal\Core\Entity\EntityFormBuilder->getForm(Object, 'edit', Array) (Line: 226)
Drupal\views_ui\Controller\ViewsUIController->edit(Object, NULL)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 574)
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}()
call_user_func_array(Object, Array) (Line: 139)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 62)
Symfony\Component\HttpKernel\HttpKernel->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: 98)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 77)
Drupal\page_cache\StackMiddleware\PageCache->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: 628)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
Problem
We build an array of the selected items when using the InOperator where both the array keys and values are set to the selected item name. If the array key contains a period, this will cause an error when exporting this to config since sequences don't support periods in their keys
Proposed solution
Don't use an array with both keys and values set to the selected items, use a numeric array that only has the values set to the selected items
Comment | File | Size | Author |
---|---|---|---|
#45 | 2780869-45-9.1.x.patch | 36.49 KB | claudiu.cristea |
#28 | 2780869-28.test-only.patch | 4.94 KB | claudiu.cristea |
Comments
Comment #2
dawehnerGreat bug report!.
That is certainly a bug in views ... the problem is that we store things with key: value in YAML, but we use the "." to specify the hierarchy of elements. One possible solution could be to store the entries using a list rather than an a key value thing (called sequence). Another possibility would be to rewrite those values, like replacing "." with "__" or so.
Comment #3
joachim CreditAttribution: joachim at Torchbox commentedCan the report be simplified? It sounds like this could be reproduced with just an options field on nodes, where one option is '.' -- and dispense with the custom entity part.
Comment #4
jmadden27 CreditAttribution: jmadden27 commentedI'm afraid if I simplify it to document something I didn't actually do, I'll get something wrong. I'm very new to Drupal development and just outlined exactly what I did.
Comment #5
joachim CreditAttribution: joachim commentedConfirming that this is reproducible with just nodes:
- create a text options field on a node type
- add an option consisting of just a period, '.'
- create a view of nodes
- add a filter on the field, and select the period as the filter value
- save the view
BOOM:
> Drupal\Core\Config\ConfigValueException: . key contains a dot which is not supported. in Drupal\Core\Config\ConfigBase->validateKeys() (line 211 of core/lib/Drupal/Core/Config/ConfigBase.php).
Comment #6
jmadden27 CreditAttribution: jmadden27 commentedThanks Joachim! (Not sure how to reply directly to a comment.)
Comment #7
pguillard CreditAttribution: pguillard commentedThe Config system planned throws exceptions each times it finds a dot in a key - Normal
I guess we sloud escape the dot at the time the filter is saved.
Comment #8
joachim CreditAttribution: joachim commentedFurther clarification: a filter value for a text filter, such as node title, is fine. That's because the period is stored as a value, not an array key.
The problem is specifically when the filter has you choose from options, and the problem is caused by the way that the checkboxes form element returns its value: an array where the keys are the option storage values, and the values are either 0 for unchecked, or the key for checked.
> I guess we sloud escape the dot at the time the filter is saved.
Another option would be to process the checkboxes element value into a numeric array of the checked values, in other words:
Comment #9
LendudeHere are some failing tests for the handler that is used in the steps described by @joachim in #5 (list_field) and the base handler (in_operator).
Comment #10
LendudeComment #12
dhrjgpt2005@gmail.com CreditAttribution: dhrjgpt2005@gmail.com as a volunteer and at TATA Consultancy Services commentedComment #13
dhrjgpt2005@gmail.com CreditAttribution: dhrjgpt2005@gmail.com as a volunteer and at TATA Consultancy Services commentedI think to replace "." with anyother character will require lot more changes into core functions like set, validate,setData etc...
While other options suggested by @joachim would be better option and we should give a try.
@Lendude / @dawehner what you suggest on this?
Comment #14
joachim CreditAttribution: joachim commentedI occurs to me that we should compare how other module store a value that's from a form checkboxes element.
For instance, Menu UI module has a checkboxes form element in the node type settings. Those get saved like this:
So filtering as I suggested in #8 does look like the right thing to do.
Comment #16
dhrjgpt2005@gmail.com CreditAttribution: dhrjgpt2005@gmail.com as a volunteer and at TATA Consultancy Services commentedComment #19
dakku CreditAttribution: dakku as a volunteer commentedSubscribe++
Comment #20
KilianM CreditAttribution: KilianM commentedSubscribe
Need a fix
Comment #22
matt_paz CreditAttribution: matt_paz commentedJust updating the target version.
Comment #23
matt_paz CreditAttribution: matt_paz commentedComment #24
matt_paz CreditAttribution: matt_paz commentedUpdating target
Comment #27
claudiu.cristeaThis is a bug. It's 8.9.x
Comment #28
claudiu.cristeaRerolled the TEST ONLY patch from #9.
Comment #30
claudiu.cristeaHere's a fix. I wonder if we need to provide an update path. Any thoughts?
Also, this is Major as it breaks the ability so save a View in such circumstances.
Comment #31
claudiu.cristeaAdded an update path. Fixing default configs.
Comment #34
claudiu.cristeaMade the check faster in ViewsConfigUpdater (this also fixes a lot of tests).
Comment #35
claudiu.cristeaForgot a copy/paste leftover.
Comment #37
claudiu.cristeaFixing all failed tests.
Comment #38
claudiu.cristeaOptimize the ViewsConfigUpdater to avoid creating a plugin instance.
Comment #39
claudiu.cristeaAdding some return types. Reorder the methods inside ViewsConfigUpdater
Comment #40
LendudeUpdated the IS a bit to make the problem and proposed solution a bit clearer
The patch looks really good, nothing to nitpick. We have a fix, tests for the fix, update path and test for the update path.
Comment #41
alexpottThis patch needs a reroll. The solution does indeed look really nice.
This seems out-of-scope. We need to work why this variable is unused.
The comment changes here seem out-of-scope. It looks like the comments have not changed at all. Only the code has. Making changes like this increases reviewer load.
Comment #42
claudiu.cristeaWeird, the patch applied cleanly against 8.9.x. Maybe you tried against 9.1.x? As this is a bug I think it should be 8.9.x.
During development, I had that test failed. I've noticed the unused variable. Added back.
True, the code line is the only one in the method. The comment looks a little untidy as it comes to our coding standards. Reverted.
Comment #43
claudiu.cristeaRemoving the tag
Comment #44
alexpott@claudiu.cristea we have to commit the fix to 9.1.x first. So we need a 9.1.x patch before we can fix this on any other branch. Also as this contains an update function it'll need special consideration for backport to 8.9.x and 9.0.x. i.e release manager approval.
Comment #45
claudiu.cristeaOK. I'm not up-to-date with the rules on D8>D9 transition. Here's the 9.1.x patch.
Comment #46
LendudeNice, feedback addressed, back to RTBC assuming this comes back green
Comment #47
claudiu.cristeaTagging for 8.9.x backport.
Comment #48
alexpottCommitted 104bca1 and pushed to 9.1.x. Thanks!
Going to dicuss with other committers about the backport situation.
Comment #50
catchSo the config update function looks fine, but there are quite a lot of changes here overall including a new public method on a class.
Comment #51
alexpott@catch yes but it is a new method on a plugin - something that is declared as @internal and not covered by our BC promise.Yes we go out of way to not break stuff but at the same time this bug has no work around.
Comment #52
alexpottWhile reviewing this for backport I've got more and more concerned about potential BC impacts of this change. If we need to make this fix here - then what about contrib. InOperator is extended from a lot - see http://grep.xnddx.ru/search?text=InOperator&filename= - so there's a very good chance of this causing issues.
I think we need to consider only fixing the configuration but maintaining the same structure once the config is loaded. We did something similar for fields and list values.
This conditional part gives me concern too. Why is this necessary? If someone resaved a view via the UI isn't the array_values() going to kick in the keys be ignored. Or does this exist to make this reentrant? So we can tell a fixed array from a not fixed one? If so I think we should consider documenting this different.
Also I think we should check the class before checking the values as that is more logical and less surprising. It might not be as performant but I'm not sure that it matters too much - or if it really is more performant this way around.
Given the BC concerns in point 1 and after discussions with @catch I've decided to revert this for now. Better than regretting it later. It'd be great if people who've worked on the issue can have a think about contrib and possible BC impacts and ways we can mitigate them. Sorry doing the revert but I think it's the best course of action given the concerns.
Comment #54
claudiu.cristea@alexpott, could you, please, point me to code for fields and list values?
Comment #57
manjushp CreditAttribution: manjushp commentedBased on comment #45, I patched up all the 37 files and I still get the same error
Drupal\Core\Config\ConfigValueException: es_attachment.data key contains a dot which is not supported. in Drupal\Core\Config\ConfigBase->validateKeys() (line 211 of /opt/rh/httpd24/root/var/www/html/dcu/web/core/lib/Drupal/Core/Config/ConfigBase.php).
I just updated my core to 9.2-dev