Script Loader: Preserve duplicate query variables in enqueued script and style URLs.#11164
Script Loader: Preserve duplicate query variables in enqueued script and style URLs.#11164westonruter wants to merge 8 commits intoWordPress:trunkfrom
Conversation
…and style URLs. Previously, using 'add_query_arg()' to append versions or handle-specific query arguments would strip any existing duplicate query variables in the source URL (common in Google Fonts URLs). This change refactors 'WP_Styles::_css_href()' and 'WP_Scripts::do_item()' to manually append these parameters to the URL string. This ensures all original query variables are preserved exactly as provided. It also improves fragment handling by ensuring query parameters are inserted before any '#' anchor while maintaining the anchor's presence. Regression tests are added to verify preservation of duplicate query variables and fragments using 'WP_HTML_Tag_Processor' for precise attribute verification. Follow-up to r61397. See #64372. Co-authored-by: gemini-cli <176961590+gemini-code-assist[bot]@users.noreply.github.com>
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Refactors the assignment of '' in 'WP_Styles::_css_href()' and 'WP_Scripts::do_item()' to use the more concise null coalescing operator. Co-authored-by: gemini-cli <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-cli <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-cli <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
There was a problem hiding this comment.
Pull request overview
This PR updates WordPress’s script/style URL building to avoid add_query_arg() re-parsing query strings (which drops duplicate query variables), preserving the original query string (including duplicates) and ensuring new parameters are inserted before any #fragment.
Changes:
- Refactors
WP_Styles::_css_href()andWP_Scripts::do_item()to appendverand handle args directly onto the URL string (preserving duplicate query vars). - Improves fragment handling by ensuring appended query parameters are added before
#anchorwhile retaining the fragment. - Adds regression tests asserting preservation of duplicate query vars and fragments via
WP_HTML_Tag_Processor, plus updates expected markup fixtures affected by the encoding behavior change.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
src/wp-includes/class-wp-styles.php |
Builds style href without add_query_arg() to preserve duplicate query vars and handle fragments correctly. |
src/wp-includes/class-wp-scripts.php |
Builds script src without add_query_arg() to preserve duplicate query vars and handle fragments correctly. |
tests/phpunit/tests/dependencies/styles.php |
Adds regression tests validating duplicate query var + fragment preservation for enqueued styles. |
tests/phpunit/tests/dependencies/scripts.php |
Updates fixture expectations impacted by URL encoding behavior and adds regression tests for scripts. |
Comments suppressed due to low confidence (2)
src/wp-includes/class-wp-styles.php:420
$added_argsis cast to string, but the subsequent truthy checks (if ( $ver_to_add || $added_args )/if ( $added_args )) will treat the valid query string value'0'as false and skip appending it. This is a behavior change vs the previousparse_str()/add_query_arg()path, which would still include a?0handle arg.
Use explicit empty-string checks (e.g. '' !== $added_args) so ?0 is preserved, while still skipping the default empty string.
$added_args = (string) ( $this->args[ $handle ] ?? '' );
if ( $ver_to_add || $added_args ) {
$fragment = strstr( $src, '#' );
src/wp-includes/class-wp-scripts.php:430
$added_argsis a string, but the truthy checks (if ( $ver_to_add || $added_args )/if ( $added_args )) will treat'0'as false and skip appending it. With a handle likefoo?0, the0arg would now be dropped, whereas the priorparse_str()/add_query_arg()flow would preserve it.
Consider using explicit empty-string checks (e.g. '' !== $added_args) so ?0 is preserved.
$added_args = (string) ( $this->args[ $handle ] ?? '' );
if ( $ver_to_add || $added_args ) {
$fragment = strstr( $src, '#' );
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: gemini-cli <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
Fix tested successfully: #10608 (comment) |
Consolidates redundant duplicate query variable and fragment tests into consolidated methods with associative data providers. Adds native PHP type hints for parameters and return values, along with PHPStan array shape documentation. Also applies standard WordPress code formatting. Co-authored-by: gemini-cli <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Updates regression tests to include coverage for 'false' version strings, which trigger the default WordPress version. Also refines parameter type hints to accurately reflect allowed 'string|bool|null' values. Co-authored-by: gemini-cli <176961590+gemini-code-assist[bot]@users.noreply.github.com>
sirreal
left a comment
There was a problem hiding this comment.
Very interesting issue. The fix seems appropriate.
…s and styles. Previously in r61397, `add_query_arg()` was used to append versions or handle-specific query arguments. This resulted in stripping any existing duplicate query variables in the source URL (common in Google Fonts URLs). This change refactors `WP_Styles::_css_href()` and `WP_Scripts::do_item()` to manually append these parameters to the URL string. This ensures all original query variables are preserved exactly as provided. It also improves fragment handling by ensuring query parameters are inserted before any '#' anchor while maintaining the anchor's presence. The URL encoding changes in `tests/phpunit/tests/dependencies/scripts.php` are reversions of what had previously been done in r61397. Developed in #11164 Follow-up to r61397, r61358. Props westonruter, jonsurrell. Fixes #64372. git-svn-id: https://develop.svn.wordpress.org/trunk@61927 602fd350-edb4-49c9-b593-d223f7449a82
…s and styles. Previously in r61397, `add_query_arg()` was used to append versions or handle-specific query arguments. This resulted in stripping any existing duplicate query variables in the source URL (common in Google Fonts URLs). This change refactors `WP_Styles::_css_href()` and `WP_Scripts::do_item()` to manually append these parameters to the URL string. This ensures all original query variables are preserved exactly as provided. It also improves fragment handling by ensuring query parameters are inserted before any '#' anchor while maintaining the anchor's presence. The URL encoding changes in `tests/phpunit/tests/dependencies/scripts.php` are reversions of what had previously been done in r61397. Developed in WordPress/wordpress-develop#11164 Follow-up to r61397, r61358. Props westonruter, jonsurrell. Fixes #64372. Built from https://develop.svn.wordpress.org/trunk@61927 git-svn-id: http://core.svn.wordpress.org/trunk@61209 1a063a9b-81f0-0310-95a4-ce76da25c4cd
Previously, using
add_query_arg()to append versions or handle-specific query arguments would strip any existing duplicate query variables in the source URL (common in Google Fonts URLs).This change refactors
WP_Styles::_css_href()andWP_Scripts::do_item()to manually append these parameters to the URL string. This ensures all original query variables are preserved exactly as provided. It also improves fragment handling by ensuring query parameters are inserted before any '#' anchor while maintaining the anchor's presence.Regression tests are added to verify preservation of duplicate query variables and fragments using
WP_HTML_Tag_Processorfor precise attribute verification.The URL encoding changes in
tests/phpunit/tests/dependencies/scripts.phpare reversions of what had previously been done in c4d8047.Follow-up to r61397.
Props @nichita231.
See #64372.
This issue would have been impacted quite a few themes and plugins:
Trac ticket: https://core.trac.wordpress.org/ticket/64372
Use of AI Tools
I iterated with Gemini CLI on adding tests to reproduce the issue, and then to iterated back and forth on changes. Then I had Gemini draft a commit message and commit.
Prompts
Initial instruction regarding
add_query_arg()eliminating repeated query vars inWP_StylesandWP_Scripts, with a request for a better solution and unit tests.Don't add a new test file. Just add to the existing files which were previously modified in c4d8047. Add the new tests in the appropriate spot, probably right after the tests added in that commit to those two files
You can supply --group=64372 to just one call to npm run test:php
As opposed to using assertStringContainsString, it would be better to assert on the entire URL being the same. Let's provide 'https://example.com/' URLs for each script and style and add assetions to assertSame for the entire string
Let's actually compare URLs. Extract the href/src from the tag via the WP_HTML_Tag_Processor and then compare the attribute value with the expected URL
Let's also add assertTrue() checks to the next_tag calls
ok, now you provided an abbreviated "$frag" variable. Let's avoid this abbreviation. use $fragment
None of the tests provide any URLs with fragments
Wouldn't it make sense to skip setting $fragment to an empy string if strstr() returns false, and then to only append $fragment onto $src if it is a string?
for the tests, the phpdoc descriptions should all use 3rd singular person verbs to start (e.g. "Tests")
I see there are failures now when I run
pm run test:php -- --group=scriptsI think you should rather change the URLs back to what they had been beforec c4d8047. YOu can see that I had changed the URLs to deal with the encoding change
That doesn't look relevant. I mean literally to undo the fixture changes I had made in c4d8047.
Your sed commands keep failing.
ok, now based on all of the changes we've made together, and the changes which are staged in git, write a commit message and commit
This code doesn't seem ideal:
It should rather be:
Add a new commit
There is redundancy in this code:
I think it should set $added_ver to $this->default_version or (string) $obj->ver and then below if
$added_veris not '', then append 'ver=' . rawurlencode( $added_ver )You can simplify the commit message without the additional references or component name. Refer to the previous commit as an exmaple
This looks strange:
( '' !== $ver_to_add || $added_args). Why compare with empty string for one but not the other. Can't they both just be truthy checks since they are both guaranteed to be strings?This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.