diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index a60fce6262744..ffb2fffa5c9d1 100644 --- a/src/wp-includes/script-loader.php +++ b/src/wp-includes/script-loader.php @@ -3010,7 +3010,18 @@ function wp_maybe_inline_styles() { $path = $wp_styles->get_data( $handle, 'path' ); if ( $path && $src ) { $size = wp_filesize( $path ); - if ( ! $size ) { + if ( 0 === $size && ! file_exists( $path ) ) { + _doing_it_wrong( + __FUNCTION__, + sprintf( + /* translators: 1: 'path', 2: filesystem path, 3: style handle */ + __( 'Unable to read the "%1$s" key with value "%2$s" for stylesheet "%3$s".' ), + 'path', + esc_html( $path ), + esc_html( $handle ) + ), + '7.0.0' + ); continue; } $styles[] = array( @@ -3048,6 +3059,20 @@ static function ( $a, $b ) { } // Get the styles if we don't already have them. + if ( ! is_readable( $style['path'] ) ) { + _doing_it_wrong( + __FUNCTION__, + sprintf( + /* translators: 1: 'path', 2: filesystem path, 3: style handle */ + __( 'Unable to read the "%1$s" key with value "%2$s" for stylesheet "%3$s".' ), + 'path', + esc_html( $style['path'] ), + esc_html( $style['handle'] ) + ), + '7.0.0' + ); + continue; + } $style['css'] = file_get_contents( $style['path'] ); /* diff --git a/tests/phpunit/tests/dependencies/styles.php b/tests/phpunit/tests/dependencies/styles.php index c1c11985190cf..57687752f6a08 100644 --- a/tests/phpunit/tests/dependencies/styles.php +++ b/tests/phpunit/tests/dependencies/styles.php @@ -716,10 +716,12 @@ public function test_wp_maybe_inline_styles_multiple_runs() { /** * @ticket 58394 + * @ticket 64447 * * @covers ::wp_maybe_inline_styles + * @expectedIncorrectUsage wp_maybe_inline_styles */ - public function test_test_wp_maybe_inline_styles_missing_file() { + public function test_wp_maybe_inline_styles_missing_file() { $filter = new MockAction(); add_filter( 'pre_wp_filesize', array( $filter, 'filter' ) ); $url = '/' . WPINC . '/css/invalid.css'; @@ -768,6 +770,70 @@ public function test_wp_maybe_inline_styles_no_path() { $this->assertSame( $GLOBALS['wp_styles']->registered['test-handle']->src, $url ); } + /** + * @ticket 64447 + * + * @covers ::wp_maybe_inline_styles + * @expectedIncorrectUsage wp_maybe_inline_styles + */ + public function test_wp_maybe_inline_styles_bad_path_with_file_size_provided() { + $style_path = '/css/invalid.css'; // Does not exist. + + // This ensures the initial file size check is bypassed. + add_filter( + 'pre_wp_filesize', + static function ( $size, $path ) use ( $style_path ) { + if ( str_contains( $path, $style_path ) ) { + $size = 1000; + } + return $size; + }, + 10, + 2 + ); + + $handle = 'test-handle'; + $url = '/' . WPINC . $style_path; + wp_register_style( $handle, $url ); + wp_style_add_data( $handle, 'path', ABSPATH . WPINC . $style_path ); + wp_enqueue_style( $handle ); + + wp_maybe_inline_styles(); + + $this->assertSame( $GLOBALS['wp_styles']->registered[ $handle ]->src, $url ); + } + + /** + * @ticket 64447 + * + * @covers ::wp_maybe_inline_styles + */ + public function test_wp_maybe_inline_styles_good_path_with_zero_file_size_provided() { + $style_path = '/css/classic-themes.css'; + + // This simulates the file having a zero size. + add_filter( + 'pre_wp_filesize', + static function ( $size, $path ) use ( $style_path ) { + if ( str_contains( $path, $style_path ) ) { + $size = 0; + } + return $size; + }, + 10, + 2 + ); + + $handle = 'test-handle'; + wp_register_style( $handle, '/' . WPINC . $style_path ); + wp_style_add_data( $handle, 'path', ABSPATH . WPINC . $style_path ); + wp_enqueue_style( $handle ); + + wp_maybe_inline_styles(); + + $this->assertFalse( $GLOBALS['wp_styles']->registered[ $handle ]->src ); + } + /** * @ticket 63887 */ diff --git a/tests/phpunit/tests/media.php b/tests/phpunit/tests/media.php index 1ab836fe856d8..f6b1e5b2d982b 100644 --- a/tests/phpunit/tests/media.php +++ b/tests/phpunit/tests/media.php @@ -6677,6 +6677,10 @@ static function () { * @dataProvider data_provider_data_provider_to_test_wp_enqueue_img_auto_sizes_contain_css_fix */ public function test_wp_enqueue_img_auto_sizes_contain_css_fix( ?Closure $set_up, bool $expected, ?string $expected_deprecated = null ): void { + // These files are created as part of the build process, but the unit tests don't run the build prior to running unit tests on GHA. + self::touch( ABSPATH . WPINC . '/css/dist/block-library/style.css' ); + self::touch( ABSPATH . WPINC . '/css/dist/block-library/common.css' ); + if ( $set_up ) { $set_up(); } diff --git a/tests/phpunit/tests/template.php b/tests/phpunit/tests/template.php index a304fff95f865..a965665360b05 100644 --- a/tests/phpunit/tests/template.php +++ b/tests/phpunit/tests/template.php @@ -1677,6 +1677,9 @@ function (): void { * @dataProvider data_wp_hoist_late_printed_styles */ public function test_wp_hoist_late_printed_styles( ?Closure $set_up, int $inline_size_limit, array $expected_styles ): void { + // `_print_emoji_detection_script()` assumes `wp-includes/js/wp-emoji-loader.js` is present: + self::touch( ABSPATH . WPINC . '/js/wp-emoji-loader.js' ); + switch_theme( 'default' ); global $wp_styles; $wp_styles = null; @@ -1711,6 +1714,8 @@ static function () { 'wp-block-library', wp_should_load_separate_core_block_assets() ? 'css/dist/block-library/common.css' : 'css/dist/block-library/style.css' ); + $this->ensure_style_asset_file_created( 'wp-block-library-theme', 'css/dist/block-library/theme.css' ); + if ( wp_should_load_separate_core_block_assets() ) { $this->ensure_style_asset_file_created( 'wp-block-separator', 'blocks/separator/style.css' ); } @@ -1827,11 +1832,8 @@ private function ensure_style_asset_file_created( string $handle, string $relati } $dependency->src = includes_url( $relative_path ); $path = ABSPATH . WPINC . '/' . $relative_path; - if ( ! file_exists( $path ) ) { - $dir = dirname( $path ); - if ( ! file_exists( $dir ) ) { - mkdir( $dir, 0777, true ); - } + self::touch( $path ); + if ( 0 === filesize( $path ) ) { file_put_contents( $path, "/* CSS for $handle */" ); } wp_style_add_data( $handle, 'path', $path );