Problem/Motivation
Redirects with periods in the query string (.) have those converted to underscores (_). This is actually due to core's Url::fromUri() method's use of parse_str:
if (!empty($uri_parts['query'])) {
$uri_query = [];
parse_str($uri_parts['query'], $uri_query);
$uri_options['query'] = isset($uri_options['query']) ? $uri_options['query'] + $uri_query : $uri_query;
unset($uri_parts['query']);
}
Proposed resolution
Either provide a workaround in the Redirect module, or fix upstream. If this issue happens with manually created menu links in core, then I'd recommend fixing there, but otherwise this seems like something that only Redirect might encounter.
Remaining tasks
User interface changes
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|---|---|---|
| #4 | LinksWhileEditing.png | 88.33 KB | malte.koelle |
| #4 | LinksAfterSaving.png | 25.83 KB | malte.koelle |
| #2 | 3153360-02-TEST-ONLY.patch | 1.11 KB | jhedstrom |
Comments
Comment #2
jhedstromTest-only patch to demonstrate the issue.
Comment #4
malte.koelle commentedThe problem is that parse_str converts the query string to an array like this:
But PHP variables cannot contain dots, so it just converts it to underscores.
But this issue also appears with manually created links outside the redirect module.
Steps to reproduce:
- Create a content type with a Link Field.
- Create a node of the content type and add an internal link with query parameters. (example: /node/1?special.chars=foo.bar) 'LinksWhileEditing.png'
- After saving the node, the Link will be displayed with underscores instead of dots. (/node/1?special_chars=foo.bar) 'LinksAfterSaving.png'
Therefore I guess it would make sense to open a core issue.
Comment #5
jhedstrom@malte.koelle thanks for that research! It does indeed seem like a core issue should be open since this impacts link fields (which by-design should allow any external link with query parameters to be used.)
Comment #6
aaronpinero commentedI think the problem is in Drupal/Core/Url.php, specifically line 307:
parse_str($uri_parts['query'], $uri_query);
The PHP manual states "Because variables in PHP can't have dots and spaces in their names, those are converted to underscores. Same applies to naming of respective key names in case of using this function with result parameter."
I'm surprised that this is a bug because it's come up before (in Drupal 7) and supposedly patched. See https://www.drupal.org/project/link/issues/1616752
Comment #7
aaronpinero commentedThere are a few other places where this might also need to be corrected because of use of parse_str on query strings:
core/modules/views/src/Plugin/views/field/FieldPluginBase.php around line 1548
core/lib/Drupal/Component/Utility/UrlHelper.php around line 163
On my own site, I replaced the parse_str instruction in each place with some version of:
$query_pairs = explode("&", {{query_string}});
foreach ($query_pairs as $pair) {
$pair_array = explode("=", $pair);
if (count($pair_array) < 2) {
array_push($pair_array,'');
}
list($k, $v) = array_map("urldecode", $pair_array);
{{output_array}}[$k] = $v;
}
This code is a minor modification of the solution from the Drupal 7 Link module patch in the issue I referenced previously. Not sure if this is the most effective solution, but it did have the desired result on my own site.
In a search of core, there seem to be several other places where parse_str is being used on query strings, so there may be other places where the problem exists but doesn't affect my particular use case.
Comment #8
aaronpinero commentedI found this core issue which has patches for Drupal 8.9 and 9.1:
https://www.drupal.org/project/drupal/issues/2984272
Comment #9
aaronpinero commented