Make WordPress Core


Ignore:
Timestamp:
03/11/2026 01:30:24 AM (7 months ago)
Author:
westonruter
Message:

Script Loader: Preserve duplicate URL query params in enqueued scripts 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 ​https://github.com/WordPress/wordpress-develop/pull/11164

Follow-up to r61397, r61358.

Props westonruter, jonsurrell.
Fixes #64372.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/dependencies/styles.php

    r61519 r61927  
    963963
    964964        /**
     965         * Tests that duplicate query vars and fragments are preserved in styles.
     966         *
     967         * @ticket 64372
     968         *
     969         * @dataProvider data_duplicate_query_vars_and_fragments_preserved_in_styles
     970         *
     971         * @param string           $src          The stylesheet's source URL.
     972         * @param string|bool|null $ver          The style's version.
     973         * @param string           $expected_url The expected URL.
     974         * @param string           $handle       Optional. The style's registered handle. Default 'test-style'.
     975         */
     976        public function test_duplicate_query_vars_and_fragments_preserved_in_styles( string $src, $ver, string $expected_url, string $handle = 'test-style' ): void {
     977                wp_enqueue_style( $handle, $src, array(), $ver );
     978                $output    = get_echo( 'wp_print_styles' );
     979                $processor = new WP_HTML_Tag_Processor( $output );
     980
     981                $this->assertTrue( $processor->next_tag( 'link' ) );
     982                $this->assertSame( $expected_url, $processor->get_attribute( 'href' ) );
     983        }
     984
     985        /**
     986         * Data provider for test_duplicate_query_vars_and_fragments_preserved_in_styles.
     987         *
     988         * @return array<string, array{src: string, ver: string|bool|null, expected_url: string, handle?: string}> Data provider.
     989         */
     990        public function data_duplicate_query_vars_and_fragments_preserved_in_styles(): array {
     991                $ver = get_bloginfo( 'version' );
     992
     993                return array(
     994                        'duplicate query vars'                => array(
     995                                'src'          => 'https://fonts.googleapis.com/css2?family=Figtree:wght@300;400;500;600;700&family=Montserrat:wght@700&display=swap',
     996                                'ver'          => '1.0',
     997                                'expected_url' => 'https://fonts.googleapis.com/css2?family=Figtree:wght@300;400;500;600;700&family=Montserrat:wght@700&display=swap&ver=1.0',
     998                        ),
     999                        'duplicate query vars, null version'  => array(
     1000                                'src'          => 'https://fonts.googleapis.com/css2?family=Figtree:wght@300;400;500;600;700&family=Montserrat:wght@700&display=swap',
     1001                                'ver'          => null,
     1002                                'expected_url' => 'https://fonts.googleapis.com/css2?family=Figtree:wght@300;400;500;600;700&family=Montserrat:wght@700&display=swap',
     1003                        ),
     1004                        'duplicate query vars, false version' => array(
     1005                                'src'          => 'https://fonts.googleapis.com/css2?family=Figtree:wght@300;400;500;600;700&family=Montserrat:wght@700&display=swap',
     1006                                'ver'          => false,
     1007                                'expected_url' => "https://fonts.googleapis.com/css2?family=Figtree:wght@300;400;500;600;700&family=Montserrat:wght@700&display=swap&ver=$ver",
     1008                        ),
     1009                        'duplicate query vars in handle'      => array(
     1010                                'src'          => 'https://example.com/test-style.css',
     1011                                'ver'          => '1.0',
     1012                                'expected_url' => 'https://example.com/test-style.css?ver=1.0&a=1&a=2',
     1013                                'handle'       => 'test-style?a=1&a=2',
     1014                        ),
     1015                        'duplicate query vars and fragments'  => array(
     1016                                'src'          => 'https://example.com/style.css?arg=1&arg=2#anchor',
     1017                                'ver'          => '1.0',
     1018                                'expected_url' => 'https://example.com/style.css?arg=1&arg=2&ver=1.0#anchor',
     1019                        ),
     1020                        'zero query var in handle'            => array(
     1021                                'src'          => 'https://example.com/test-style.css',
     1022                                'ver'          => '1.0',
     1023                                'expected_url' => 'https://example.com/test-style.css?ver=1.0&0',
     1024                                'handle'       => 'test-style?0',
     1025                        ),
     1026                );
     1027        }
     1028
     1029        /**
    9651030         * Data provider for:
    9661031         * - test_varying_versions_added_to_handle_args_enqueued_styles
Note: See TracChangeset for help on using the changeset viewer.