Problem/Motivation
When FormOperations::setAjaxWorkspace() processes a form element that already has token or persist in its #ajax['options']['query'] (but no workspace key), the use of array_merge_recursive() converts these scalar values into arrays. This causes Symfony's InputBag::get() to throw a BadRequestException: "Input value contains a non-scalar value."
Steps to reproduce
This can occur when modules like Media Library copy request parameters to form elements, and those parameters already contain workspace-related values from a previous AJAX request. Hopefully (or hopefully not?), others run into this and help with the steps to reproduce because I'm not totally sure how to reproduce this on vanilla Drupal core because my use case has a lot of stuff going on, but it is something like
- Enable Workspaces module
- Create and switch to a non-default workspace
- Build a workspace-safe form with an AJAX element that has pre-existing token or persist query params (simulating what happens when Media Library copies request params)
- The resulting #ajax['options']['query'] will contain arrays instead of scalars:
- token becomes ['workspace-token', 'pre-existing-token']
- persist becomes [false, '']
Proposed resolution
Replace array_merge_recursive() with array_replace() in FormOperations::setAjaxWorkspace(). This ensures workspace parameters always remain scalar values, with the current workspace's values taking precedence over any pre-existing values.
<?php
// Before
if (isset($element['#ajax']) && !isset($element['#ajax']['options']['query']['workspace'])) {
$element['#ajax']['options']['query'] = array_merge_recursive(
$url_query_options,
$element['#ajax']['options']['query'] ?? [],
);
}
// After
if (isset($element['#ajax'])) {
$existing_query = $element['#ajax']['options']['query'] ?? [];
$element['#ajax']['options']['query'] = NestedArray::mergeDeep($existing_query, $url_query_options);
}
?>Issue fork drupal-3569751
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
quietone commentedThe main development branch is 'main'. Changes are made on the main branch first, and are then back ported as needed according to the Core change policies. The version the problem was discovered on should be stated in the issue summary Problem/Motivation section. Thanks.
There is no merge request here so changing status.
Comment #7
tim bozeman commentedComment #8
tim bozeman commentedComment #9
tim bozeman commentedComment #10
amateescu commentedReviewed the MR :)
Comment #11
tim bozeman commentedThank you for reviewing amateescu! I consolidated the test form and assertions.
Comment #12
amateescu commentedLooks great now :)
Comment #13
alexpottCommitted and pushed 86416c4ca4e to main and 58d66871534 to 11.x and 4d6e1e226cd to 11.3.x. Thanks!