Make WordPress Core

Changeset 61927


Ignore:
Timestamp:
03/11/2026 01:30:24 AM (2 weeks 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.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-scripts.php

    r61699 r61927  
    418418        }
    419419
    420         $query_args = array();
     420        $ver_to_add = '';
    421421        if ( empty( $obj->ver ) && null !== $obj->ver && is_string( $this->default_version ) ) {
    422             $query_args['ver'] = $this->default_version;
     422            $ver_to_add = $this->default_version;
    423423        } elseif ( is_scalar( $obj->ver ) ) {
    424             $query_args['ver'] = (string) $obj->ver;
    425         }
    426         if ( isset( $this->args[ $handle ] ) ) {
    427             parse_str( $this->args[ $handle ], $parsed_args );
    428             if ( $parsed_args ) {
    429                 $query_args = array_merge( $query_args, $parsed_args );
    430             }
    431         }
    432         $src = add_query_arg( rawurlencode_deep( $query_args ), $src );
     424            $ver_to_add = (string) $obj->ver;
     425        }
     426
     427        $added_args = (string) ( $this->args[ $handle ] ?? '' );
     428
     429        if ( '' !== $ver_to_add || '' !== $added_args ) {
     430            $fragment = strstr( $src, '#' );
     431            if ( false !== $fragment ) {
     432                $src = substr( $src, 0, -strlen( $fragment ) );
     433            }
     434
     435            if ( '' !== $ver_to_add ) {
     436                $src .= ( str_contains( $src, '?' ) ? '&' : '?' ) . 'ver=' . rawurlencode( $ver_to_add );
     437            }
     438            if ( '' !== $added_args ) {
     439                $src .= ( str_contains( $src, '?' ) ? '&' : '?' ) . $added_args;
     440            }
     441
     442            if ( false !== $fragment ) {
     443                $src .= $fragment;
     444            }
     445        }
    433446
    434447        /** This filter is documented in wp-includes/class-wp-scripts.php */
  • trunk/src/wp-includes/class-wp-styles.php

    r61542 r61927  
    408408        }
    409409
    410         $query_args = array();
     410        $ver_to_add = '';
    411411        if ( empty( $ver ) && null !== $ver && is_string( $this->default_version ) ) {
    412             $query_args['ver'] = $this->default_version;
     412            $ver_to_add = $this->default_version;
    413413        } elseif ( is_scalar( $ver ) ) {
    414             $query_args['ver'] = (string) $ver;
    415         }
    416         if ( isset( $this->args[ $handle ] ) ) {
    417             parse_str( $this->args[ $handle ], $parsed_args );
    418             if ( $parsed_args ) {
    419                 $query_args = array_merge( $query_args, $parsed_args );
    420             }
    421         }
    422         $src = add_query_arg( rawurlencode_deep( $query_args ), $src );
     414            $ver_to_add = (string) $ver;
     415        }
     416
     417        $added_args = (string) ( $this->args[ $handle ] ?? '' );
     418
     419        if ( '' !== $ver_to_add || '' !== $added_args ) {
     420            $fragment = strstr( $src, '#' );
     421            if ( false !== $fragment ) {
     422                $src = substr( $src, 0, -strlen( $fragment ) );
     423            }
     424
     425            if ( '' !== $ver_to_add ) {
     426                $src .= ( str_contains( $src, '?' ) ? '&' : '?' ) . 'ver=' . rawurlencode( $ver_to_add );
     427            }
     428            if ( '' !== $added_args ) {
     429                $src .= ( str_contains( $src, '?' ) ? '&' : '?' ) . $added_args;
     430            }
     431
     432            if ( false !== $fragment ) {
     433                $src .= $fragment;
     434            }
     435        }
    423436
    424437        /**
  • trunk/tests/phpunit/tests/dependencies/scripts.php

    r61611 r61927  
    632632//# sourceURL=blocking-not-async-without-dependency-js-before
    633633</script>
    634 <script src='https://example.com/external.js?script_event_log=blocking-not-async-without-dependency%3A+script' id='blocking-not-async-without-dependency-js'></script>
     634<script src='https://example.com/external.js?script_event_log=blocking-not-async-without-dependency:%20script' id='blocking-not-async-without-dependency-js'></script>
    635635<script id="blocking-not-async-without-dependency-js-after">
    636636scriptEventLog.push( "blocking-not-async-without-dependency: after inline" )
     
    641641//# sourceURL=async-with-blocking-dependency-js-before
    642642</script>
    643 <script src='https://example.com/external.js?script_event_log=async-with-blocking-dependency%3A+script' id='async-with-blocking-dependency-js' data-wp-strategy='async'></script>
     643<script src='https://example.com/external.js?script_event_log=async-with-blocking-dependency:%20script' id='async-with-blocking-dependency-js' data-wp-strategy='async'></script>
    644644<script id="async-with-blocking-dependency-js-after">
    645645scriptEventLog.push( "async-with-blocking-dependency: after inline" )
     
    673673//# sourceURL=async-no-dependency-js-before
    674674</script>
    675 <script src='https://example.com/external.js?script_event_log=async-no-dependency%3A+script' id='async-no-dependency-js' data-wp-strategy='async'></script>
     675<script src='https://example.com/external.js?script_event_log=async-no-dependency:%20script' id='async-no-dependency-js' data-wp-strategy='async'></script>
    676676<script id="async-no-dependency-js-after">
    677677scriptEventLog.push( "async-no-dependency: after inline" )
     
    682682//# sourceURL=async-one-async-dependency-js-before
    683683</script>
    684 <script src='https://example.com/external.js?script_event_log=async-one-async-dependency%3A+script' id='async-one-async-dependency-js' data-wp-strategy='async'></script>
     684<script src='https://example.com/external.js?script_event_log=async-one-async-dependency:%20script' id='async-one-async-dependency-js' data-wp-strategy='async'></script>
    685685<script id="async-one-async-dependency-js-after">
    686686scriptEventLog.push( "async-one-async-dependency: after inline" )
     
    691691//# sourceURL=async-two-async-dependencies-js-before
    692692</script>
    693 <script src='https://example.com/external.js?script_event_log=async-two-async-dependencies%3A+script' id='async-two-async-dependencies-js' data-wp-strategy='async'></script>
     693<script src='https://example.com/external.js?script_event_log=async-two-async-dependencies:%20script' id='async-two-async-dependencies-js' data-wp-strategy='async'></script>
    694694<script id="async-two-async-dependencies-js-after">
    695695scriptEventLog.push( "async-two-async-dependencies: after inline" )
     
    715715//# sourceURL=async-with-blocking-dependent-js-before
    716716</script>
    717 <script src='https://example.com/external.js?script_event_log=async-with-blocking-dependent%3A+script' id='async-with-blocking-dependent-js' data-wp-strategy='async'></script>
     717<script src='https://example.com/external.js?script_event_log=async-with-blocking-dependent:%20script' id='async-with-blocking-dependent-js' data-wp-strategy='async'></script>
    718718<script id="async-with-blocking-dependent-js-after">
    719719scriptEventLog.push( "async-with-blocking-dependent: after inline" )
     
    724724//# sourceURL=blocking-dependent-of-async-js-before
    725725</script>
    726 <script src='https://example.com/external.js?script_event_log=blocking-dependent-of-async%3A+script' id='blocking-dependent-of-async-js'></script>
     726<script src='https://example.com/external.js?script_event_log=blocking-dependent-of-async:%20script' id='blocking-dependent-of-async-js'></script>
    727727<script id="blocking-dependent-of-async-js-after">
    728728scriptEventLog.push( "blocking-dependent-of-async: after inline" )
     
    748748//# sourceURL=async-with-defer-dependent-js-before
    749749</script>
    750 <script src='https://example.com/external.js?script_event_log=async-with-defer-dependent%3A+script' id='async-with-defer-dependent-js' data-wp-strategy='async'></script>
     750<script src='https://example.com/external.js?script_event_log=async-with-defer-dependent:%20script' id='async-with-defer-dependent-js' data-wp-strategy='async'></script>
    751751<script id="async-with-defer-dependent-js-after">
    752752scriptEventLog.push( "async-with-defer-dependent: after inline" )
     
    757757//# sourceURL=defer-dependent-of-async-js-before
    758758</script>
    759 <script src='https://example.com/external.js?script_event_log=defer-dependent-of-async%3A+script' id='defer-dependent-of-async-js' data-wp-strategy='defer'></script>
     759<script src='https://example.com/external.js?script_event_log=defer-dependent-of-async:%20script' id='defer-dependent-of-async-js' data-wp-strategy='defer'></script>
    760760<script id="defer-dependent-of-async-js-after">
    761761scriptEventLog.push( "defer-dependent-of-async: after inline" )
     
    792792//# sourceURL=defer-dependent-of-blocking-bundle-of-none-js-before
    793793</script>
    794 <script src='https://example.com/external.js?script_event_log=defer-dependent-of-blocking-bundle-of-none%3A+script' id='defer-dependent-of-blocking-bundle-of-none-js' data-wp-strategy='defer'></script>
     794<script src='https://example.com/external.js?script_event_log=defer-dependent-of-blocking-bundle-of-none:%20script' id='defer-dependent-of-blocking-bundle-of-none-js' data-wp-strategy='defer'></script>
    795795<script id="defer-dependent-of-blocking-bundle-of-none-js-after">
    796796scriptEventLog.push( "defer-dependent-of-blocking-bundle-of-none: after inline" )
     
    822822//# sourceURL=blocking-bundle-member-one-js-before
    823823</script>
    824 <script src='https://example.com/external.js?script_event_log=blocking-bundle-member-one%3A+script' id='blocking-bundle-member-one-js'></script>
     824<script src='https://example.com/external.js?script_event_log=blocking-bundle-member-one:%20script' id='blocking-bundle-member-one-js'></script>
    825825<script id="blocking-bundle-member-one-js-after">
    826826scriptEventLog.push( "blocking-bundle-member-one: after inline" )
     
    831831//# sourceURL=blocking-bundle-member-two-js-before
    832832</script>
    833 <script src='https://example.com/external.js?script_event_log=blocking-bundle-member-two%3A+script' id='blocking-bundle-member-two-js'></script>
     833<script src='https://example.com/external.js?script_event_log=blocking-bundle-member-two:%20script' id='blocking-bundle-member-two-js'></script>
    834834<script id="blocking-bundle-member-two-js-after">
    835835scriptEventLog.push( "blocking-bundle-member-two: after inline" )
     
    840840//# sourceURL=defer-dependent-of-blocking-bundle-of-two-js-before
    841841</script>
    842 <script src='https://example.com/external.js?script_event_log=defer-dependent-of-blocking-bundle-of-two%3A+script' id='defer-dependent-of-blocking-bundle-of-two-js' data-wp-strategy='defer'></script>
     842<script src='https://example.com/external.js?script_event_log=defer-dependent-of-blocking-bundle-of-two:%20script' id='defer-dependent-of-blocking-bundle-of-two-js' data-wp-strategy='defer'></script>
    843843<script id="defer-dependent-of-blocking-bundle-of-two-js-after">
    844844scriptEventLog.push( "defer-dependent-of-blocking-bundle-of-two: after inline" )
     
    877877//# sourceURL=defer-dependent-of-defer-bundle-of-none-js-before
    878878</script>
    879 <script src='https://example.com/external.js?script_event_log=defer-dependent-of-defer-bundle-of-none%3A+script' id='defer-dependent-of-defer-bundle-of-none-js' data-wp-strategy='defer'></script>
     879<script src='https://example.com/external.js?script_event_log=defer-dependent-of-defer-bundle-of-none:%20script' id='defer-dependent-of-defer-bundle-of-none-js' data-wp-strategy='defer'></script>
    880880<script id="defer-dependent-of-defer-bundle-of-none-js-after">
    881881scriptEventLog.push( "defer-dependent-of-defer-bundle-of-none: after inline" )
     
    904904//# sourceURL=blocking-dependency-with-defer-following-dependency-js-before
    905905</script>
    906 <script src='https://example.com/external.js?script_event_log=blocking-dependency-with-defer-following-dependency%3A+script' id='blocking-dependency-with-defer-following-dependency-js'></script>
     906<script src='https://example.com/external.js?script_event_log=blocking-dependency-with-defer-following-dependency:%20script' id='blocking-dependency-with-defer-following-dependency-js'></script>
    907907<script id="blocking-dependency-with-defer-following-dependency-js-after">
    908908scriptEventLog.push( "blocking-dependency-with-defer-following-dependency: after inline" )
     
    913913//# sourceURL=defer-dependency-with-blocking-preceding-dependency-js-before
    914914</script>
    915 <script src='https://example.com/external.js?script_event_log=defer-dependency-with-blocking-preceding-dependency%3A+script' id='defer-dependency-with-blocking-preceding-dependency-js' data-wp-strategy='defer'></script>
     915<script src='https://example.com/external.js?script_event_log=defer-dependency-with-blocking-preceding-dependency:%20script' id='defer-dependency-with-blocking-preceding-dependency-js' data-wp-strategy='defer'></script>
    916916<script id="defer-dependency-with-blocking-preceding-dependency-js-after">
    917917scriptEventLog.push( "defer-dependency-with-blocking-preceding-dependency: after inline" )
     
    922922//# sourceURL=defer-dependent-of-blocking-and-defer-dependencies-js-before
    923923</script>
    924 <script src='https://example.com/external.js?script_event_log=defer-dependent-of-blocking-and-defer-dependencies%3A+script' id='defer-dependent-of-blocking-and-defer-dependencies-js' data-wp-strategy='defer'></script>
     924<script src='https://example.com/external.js?script_event_log=defer-dependent-of-blocking-and-defer-dependencies:%20script' id='defer-dependent-of-blocking-and-defer-dependencies-js' data-wp-strategy='defer'></script>
    925925<script id="defer-dependent-of-blocking-and-defer-dependencies-js-after">
    926926scriptEventLog.push( "defer-dependent-of-blocking-and-defer-dependencies: after inline" )
     
    949949//# sourceURL=defer-dependency-with-blocking-following-dependency-js-before
    950950</script>
    951 <script src='https://example.com/external.js?script_event_log=defer-dependency-with-blocking-following-dependency%3A+script' id='defer-dependency-with-blocking-following-dependency-js' data-wp-strategy='defer'></script>
     951<script src='https://example.com/external.js?script_event_log=defer-dependency-with-blocking-following-dependency:%20script' id='defer-dependency-with-blocking-following-dependency-js' data-wp-strategy='defer'></script>
    952952<script id="defer-dependency-with-blocking-following-dependency-js-after">
    953953scriptEventLog.push( "defer-dependency-with-blocking-following-dependency: after inline" )
     
    958958//# sourceURL=blocking-dependency-with-defer-preceding-dependency-js-before
    959959</script>
    960 <script src='https://example.com/external.js?script_event_log=blocking-dependency-with-defer-preceding-dependency%3A+script' id='blocking-dependency-with-defer-preceding-dependency-js'></script>
     960<script src='https://example.com/external.js?script_event_log=blocking-dependency-with-defer-preceding-dependency:%20script' id='blocking-dependency-with-defer-preceding-dependency-js'></script>
    961961<script id="blocking-dependency-with-defer-preceding-dependency-js-after">
    962962scriptEventLog.push( "blocking-dependency-with-defer-preceding-dependency: after inline" )
     
    967967//# sourceURL=defer-dependent-of-defer-and-blocking-dependencies-js-before
    968968</script>
    969 <script src='https://example.com/external.js?script_event_log=defer-dependent-of-defer-and-blocking-dependencies%3A+script' id='defer-dependent-of-defer-and-blocking-dependencies-js' data-wp-strategy='defer'></script>
     969<script src='https://example.com/external.js?script_event_log=defer-dependent-of-defer-and-blocking-dependencies:%20script' id='defer-dependent-of-defer-and-blocking-dependencies-js' data-wp-strategy='defer'></script>
    970970<script id="defer-dependent-of-defer-and-blocking-dependencies-js-after">
    971971scriptEventLog.push( "defer-dependent-of-defer-and-blocking-dependencies: after inline" )
     
    991991//# sourceURL=defer-with-async-dependent-js-before
    992992</script>
    993 <script src='https://example.com/external.js?script_event_log=defer-with-async-dependent%3A+script' id='defer-with-async-dependent-js' data-wp-strategy='defer'></script>
     993<script src='https://example.com/external.js?script_event_log=defer-with-async-dependent:%20script' id='defer-with-async-dependent-js' data-wp-strategy='defer'></script>
    994994<script id="defer-with-async-dependent-js-after">
    995995scriptEventLog.push( "defer-with-async-dependent: after inline" )
     
    10001000//# sourceURL=async-dependent-of-defer-js-before
    10011001</script>
    1002 <script src='https://example.com/external.js?script_event_log=async-dependent-of-defer%3A+script' id='async-dependent-of-defer-js' data-wp-strategy='async'></script>
     1002<script src='https://example.com/external.js?script_event_log=async-dependent-of-defer:%20script' id='async-dependent-of-defer-js' data-wp-strategy='async'></script>
    10031003<script id="async-dependent-of-defer-js-after">
    10041004scriptEventLog.push( "async-dependent-of-defer: after inline" )
     
    10201020//# sourceURL=defer-with-before-inline-js-before
    10211021</script>
    1022 <script src='https://example.com/external.js?script_event_log=defer-with-before-inline%3A+script' id='defer-with-before-inline-js' defer data-wp-strategy='defer'></script>
     1022<script src='https://example.com/external.js?script_event_log=defer-with-before-inline:%20script' id='defer-with-before-inline-js' defer data-wp-strategy='defer'></script>
    10231023HTML
    10241024                ,
     
    10321032                },
    10331033                'expected_markup' => <<<HTML
    1034 <script src='https://example.com/external.js?script_event_log=defer-with-after-inline%3A+script' id='defer-with-after-inline-js' data-wp-strategy='defer'></script>
     1034<script src='https://example.com/external.js?script_event_log=defer-with-after-inline:%20script' id='defer-with-after-inline-js' data-wp-strategy='defer'></script>
    10351035<script id="defer-with-after-inline-js-after">
    10361036scriptEventLog.push( "defer-with-after-inline: after inline" )
     
    10761076                },
    10771077                'expected_markup' => <<<HTML
    1078 <script src='https://example.com/external.js?script_event_log=inner-bundle-member-one%3A+script' id='inner-bundle-member-one-js' data-wp-strategy='defer'></script>
    1079 <script src='https://example.com/external.js?script_event_log=inner-bundle-member-two%3A+script' id='inner-bundle-member-two-js' data-wp-strategy='defer'></script>
    1080 <script src='https://example.com/external.js?script_event_log=outer-bundle-leaf-member%3A+script' id='outer-bundle-leaf-member-js'></script>
     1078<script src='https://example.com/external.js?script_event_log=inner-bundle-member-one:%20script' id='inner-bundle-member-one-js' data-wp-strategy='defer'></script>
     1079<script src='https://example.com/external.js?script_event_log=inner-bundle-member-two:%20script' id='inner-bundle-member-two-js' data-wp-strategy='defer'></script>
     1080<script src='https://example.com/external.js?script_event_log=outer-bundle-leaf-member:%20script' id='outer-bundle-leaf-member-js'></script>
    10811081<script id="defer-dependent-of-nested-aliases-js-before">
    10821082scriptEventLog.push( "defer-dependent-of-nested-aliases: before inline" )
    10831083//# sourceURL=defer-dependent-of-nested-aliases-js-before
    10841084</script>
    1085 <script src='https://example.com/external.js?script_event_log=defer-dependent-of-nested-aliases%3A+script' id='defer-dependent-of-nested-aliases-js' data-wp-strategy='defer'></script>
     1085<script src='https://example.com/external.js?script_event_log=defer-dependent-of-nested-aliases:%20script' id='defer-dependent-of-nested-aliases-js' data-wp-strategy='defer'></script>
    10861086<script id="defer-dependent-of-nested-aliases-js-after">
    10871087scriptEventLog.push( "defer-dependent-of-nested-aliases: after inline" )
     
    11051105                },
    11061106                'expected_markup' => <<<HTML
    1107 <script src='https://example.com/external.js?script_event_log=async1%3A+script' id='async1-js' defer data-wp-strategy='async'></script>
    1108 <script src='https://example.com/external.js?script_event_log=async2%3A+script' id='async2-js' defer data-wp-strategy='async'></script>
    1109 <script src='https://example.com/external.js?script_event_log=defer-dependent-of-async-aliases%3A+script' id='defer-dependent-of-async-aliases-js' defer data-wp-strategy='defer'></script>
     1107<script src='https://example.com/external.js?script_event_log=async1:%20script' id='async1-js' defer data-wp-strategy='async'></script>
     1108<script src='https://example.com/external.js?script_event_log=async2:%20script' id='async2-js' defer data-wp-strategy='async'></script>
     1109<script src='https://example.com/external.js?script_event_log=defer-dependent-of-async-aliases:%20script' id='defer-dependent-of-async-aliases-js' defer data-wp-strategy='defer'></script>
    11101110HTML
    11111111                ,
     
    41944194
    41954195    /**
     4196     * Tests that duplicate query vars and fragments are preserved in scripts.
     4197     *
     4198     * @ticket 64372
     4199     *
     4200     * @dataProvider data_duplicate_query_vars_and_fragments_preserved_in_scripts
     4201     *
     4202     * @param string           $src          The script's source URL.
     4203     * @param string|bool|null $ver          The script's version.
     4204     * @param string           $expected_url The expected URL.
     4205     * @param string           $handle       Optional. The script's registered handle. Default 'test-script'.
     4206     */
     4207    public function test_duplicate_query_vars_and_fragments_preserved_in_scripts( string $src, $ver, string $expected_url, string $handle = 'test-script' ): void {
     4208        wp_enqueue_script( $handle, $src, array(), $ver );
     4209        $output    = get_echo( 'wp_print_scripts' );
     4210        $processor = new WP_HTML_Tag_Processor( $output );
     4211
     4212        $this->assertTrue( $processor->next_tag( 'script' ) );
     4213        $this->assertSame( $expected_url, $processor->get_attribute( 'src' ) );
     4214    }
     4215
     4216    /**
     4217     * Data provider for test_duplicate_query_vars_and_fragments_preserved_in_scripts.
     4218     *
     4219     * @return array<string, array{src: string, ver: string|bool|null, expected_url: string, handle?: string}> Data provider.
     4220     */
     4221    public function data_duplicate_query_vars_and_fragments_preserved_in_scripts(): array {
     4222        $ver = get_bloginfo( 'version' );
     4223
     4224        return array(
     4225            'duplicate query vars'                => array(
     4226                'src'          => 'https://example.com/script.js?arg=1&arg=2',
     4227                'ver'          => '1.0',
     4228                'expected_url' => 'https://example.com/script.js?arg=1&arg=2&ver=1.0',
     4229            ),
     4230            'duplicate query vars, null version'  => array(
     4231                'src'          => 'https://example.com/script.js?arg=1&arg=2',
     4232                'ver'          => null,
     4233                'expected_url' => 'https://example.com/script.js?arg=1&arg=2',
     4234            ),
     4235            'duplicate query vars, false version' => array(
     4236                'src'          => 'https://example.com/script.js?arg=1&arg=2',
     4237                'ver'          => false,
     4238                'expected_url' => "https://example.com/script.js?arg=1&arg=2&ver=$ver",
     4239            ),
     4240            'duplicate query vars in handle'      => array(
     4241                'src'          => 'https://example.com/test-script.js',
     4242                'ver'          => '1.0',
     4243                'expected_url' => 'https://example.com/test-script.js?ver=1.0&a=1&a=2',
     4244                'handle'       => 'test-script?a=1&a=2',
     4245            ),
     4246            'duplicate query vars and fragments'  => array(
     4247                'src'          => 'https://example.com/script.js?arg=1&arg=2#anchor',
     4248                'ver'          => '1.0',
     4249                'expected_url' => 'https://example.com/script.js?arg=1&arg=2&ver=1.0#anchor',
     4250            ),
     4251            'zero query var in handle'            => array(
     4252                'src'          => 'https://example.com/test-script.js',
     4253                'ver'          => '1.0',
     4254                'expected_url' => 'https://example.com/test-script.js?ver=1.0&0',
     4255                'handle'       => 'test-script?0',
     4256            ),
     4257        );
     4258    }
     4259
     4260    /**
    41964261     * Data provider for:
    41974262     * - test_varying_versions_added_to_handle_args_enqueued_scripts
  • 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.