Make WordPress Core

Changeset 58935


Ignore:
Timestamp:
08/25/2024 11:47:01 PM (4 months ago)
Author:
peterwilsoncc
Message:

Script Loader: Refactor Etag generation for concatenated assets.

Move Etag HTTP header generation in load-scripts.php and load-styles.php to WP_Dependencies.

Introduces the method WP_Dependencies::get_etag() and associated unit tests.

Follow up to [57943].

Props vrajadas, martinkrcho, mukesh27.
Fixes #61485.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/load-scripts.php

    r58905 r58935  
    5353wp_default_packages_scripts( $wp_scripts );
    5454
    55 $etag = "WP:{$wp_version};";
    56 
    57 foreach ( $load as $handle ) {
    58     if ( ! array_key_exists( $handle, $wp_scripts->registered ) ) {
    59         continue;
    60     }
    61 
    62     $ver   = $wp_scripts->registered[ $handle ]->ver ? $wp_scripts->registered[ $handle ]->ver : $wp_version;
    63     $etag .= "{$handle}:{$ver};";
    64 }
    65 
    66 /*
    67  * This is not intended to be cryptographically secure, just a fast way to get
    68  * a fixed length string based on the script versions. As this file does not
    69  * load the full WordPress environment, it is not possible to use the salted
    70  * wp_hash() function.
    71  */
    72 $etag = 'W/"' . md5( $etag ) . '"';
     55$etag = $wp_scripts->get_etag( $load );
    7356
    7457if ( isset( $_SERVER['HTTP_IF_NONE_MATCH'] ) && stripslashes( $_SERVER['HTTP_IF_NONE_MATCH'] ) === $etag ) {
  • trunk/src/wp-admin/load-styles.php

    r58905 r58935  
    5656wp_default_styles( $wp_styles );
    5757
    58 $etag = "WP:{$wp_version};";
    59 
    60 foreach ( $load as $handle ) {
    61     if ( ! array_key_exists( $handle, $wp_styles->registered ) ) {
    62         continue;
    63     }
    64 
    65     $ver   = $wp_styles->registered[ $handle ]->ver ? $wp_styles->registered[ $handle ]->ver : $wp_version;
    66     $etag .= "{$handle}:{$ver};";
    67 }
    68 
    69 /*
    70  * This is not intended to be cryptographically secure, just a fast way to get
    71  * a fixed length string based on the script versions. As this file does not
    72  * load the full WordPress environment, it is not possible to use the salted
    73  * wp_hash() function.
    74  */
    75 $etag = 'W/"' . md5( $etag ) . '"';
     58$etag = $wp_styles->get_etag( $wp_version, $load );
    7659
    7760if ( isset( $_SERVER['HTTP_IF_NONE_MATCH'] ) && stripslashes( $_SERVER['HTTP_IF_NONE_MATCH'] ) === $etag ) {
  • trunk/src/wp-includes/class-wp-dependencies.php

    r56547 r58935  
    491491        return true;
    492492    }
     493
     494    /**
     495     * Get etag header for cache validation.
     496     *
     497     * @since 6.7.0
     498     *
     499     * @global string $wp_version The WordPress version string.
     500     *
     501     * @param string[] $load Array of script or style handles to load.
     502     * @return string Etag header.
     503     */
     504    public function get_etag( $load ) {
     505        /*
     506         * Note: wp_get_wp_version() is not used here, as this file can be included
     507         * via wp-admin/load-scripts.php or wp-admin/load-styles.php, in which case
     508         * wp-includes/functions.php is not loaded.
     509         */
     510        global $wp_version;
     511
     512        $etag = "WP:{$wp_version};";
     513
     514        foreach ( $load as $handle ) {
     515            if ( ! array_key_exists( $handle, $this->registered ) ) {
     516                continue;
     517            }
     518
     519            $ver   = $this->registered[ $handle ]->ver ?? $wp_version;
     520            $etag .= "{$handle}:{$ver};";
     521        }
     522
     523        /*
     524         * This is not intended to be cryptographically secure, just a fast way to get
     525         * a fixed length string based on the script versions. As this file does not
     526         * load the full WordPress environment, it is not possible to use the salted
     527         * wp_hash() function.
     528         */
     529        return 'W/"' . md5( $etag ) . '"';
     530    }
    493531}
  • trunk/tests/phpunit/tests/dependencies.php

    r56548 r58935  
    149149        $this->assertContains( 'one', $dep->queue );
    150150    }
     151
     152    /**
     153     * Data provider for test_get_etag.
     154     *
     155     * @return array[]
     156     */
     157    public function data_provider_get_etag() {
     158        return array(
     159            'should accept one dependency'              => array(
     160                'load'               => array(
     161                    'abcd' => '1.0.2',
     162                ),
     163                'hash_source_string' => 'WP:6.7;abcd:1.0.2;',
     164                'expected'           => 'W/"8145d7e3c41d5a9cc2bccba4afa861fc"',
     165            ),
     166            'should accept empty array of dependencies' => array(
     167                'load'               => array(),
     168                'hash_source_string' => 'WP:6.7;',
     169                'expected'           => 'W/"7ee896c19250a3d174f11469a4ad0b1e"',
     170            ),
     171        );
     172    }
     173
     174    /**
     175     * Tests get_etag method for WP_Scripts.
     176     *
     177     * @ticket 58433
     178     * @ticket 61485
     179     *
     180     * @covers WP_Dependencies::get_etag
     181     *
     182     * @dataProvider data_provider_get_etag
     183     *
     184     * @param array  $load               List of scripts to load.
     185     * @param string $hash_source_string Hash source string.
     186     * @param string $expected           Expected etag.
     187     */
     188    public function test_get_etag_scripts( $load, $hash_source_string, $expected ) {
     189        global $wp_version;
     190        // Modify global to avoid tests needing to change with each new version of WordPress.
     191        $original_wp_version = $wp_version;
     192        $wp_version          = '6.7';
     193        $instance            = wp_scripts();
     194
     195        foreach ( $load as $handle => $ver ) {
     196            // The src should not be empty.
     197            wp_enqueue_script( $handle, 'https://example.org', array(), $ver );
     198        }
     199
     200        $result = $instance->get_etag( array_keys( $load ) );
     201
     202        // Restore global prior to making assertions.
     203        $wp_version = $original_wp_version;
     204
     205        $this->assertSame( $expected, $result, "Expected MD hash: $expected for $hash_source_string, but got: $result." );
     206    }
     207
     208    /**
     209     * Tests get_etag method for WP_Styles.
     210     *
     211     * @ticket 58433
     212     * @ticket 61485
     213     *
     214     * @covers WP_Dependencies::get_etag
     215     *
     216     * @dataProvider data_provider_get_etag
     217     *
     218     * @param array  $load               List of styles to load.
     219     * @param string $hash_source_string Hash source string.
     220     * @param string $expected           Expected etag.
     221     */
     222    public function test_get_etag_styles( $load, $hash_source_string, $expected ) {
     223        global $wp_version;
     224        // Modify global to avoid tests needing to change with each new version of WordPress.
     225        $original_wp_version = $wp_version;
     226        $wp_version          = '6.7';
     227        $instance            = wp_scripts();
     228
     229        foreach ( $load as $handle => $ver ) {
     230            // The src should not be empty.
     231            wp_enqueue_style( $handle, 'https://example.cdn', array(), $ver );
     232        }
     233
     234        $result = $instance->get_etag( array_keys( $load ) );
     235
     236        // Restore global prior to making assertions.
     237        $wp_version = $original_wp_version;
     238
     239        $this->assertSame( $expected, $result, "Expected MD hash: $expected for $hash_source_string, but got: $result." );
     240    }
    151241}
Note: See TracChangeset for help on using the changeset viewer.