From 61141298c6538731d54eb35bb8fcf5d169c2e376 Mon Sep 17 00:00:00 2001 From: robelsust Date: Wed, 7 Oct 2026 12:52:08 +0600 Subject: [PATCH] Blocks: Add asset file (.asset.php) support for styles in register_block_style_handle() Adds support for reading .asset.php files for stylesheets defined in block.json via file: paths, mirroring the functionality in register_block_script_handle(). Supports custom handle names, dependencies, and versioning defined in style asset files, and falls back to existing auto-generated handles and versioning when no asset file is present. Follows up on Gutenberg #56838. Props therssoftware. --- src/wp-includes/blocks.php | 50 ++++++++---- .../data/blocks/notice/shared-style.asset.php | 7 ++ .../data/blocks/notice/shared-style.css | 3 + tests/phpunit/tests/blocks/register.php | 78 +++++++++++++++++++ 4 files changed, 124 insertions(+), 14 deletions(-) create mode 100644 tests/phpunit/data/blocks/notice/shared-style.asset.php create mode 100644 tests/phpunit/data/blocks/notice/shared-style.css diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php index beaf08d4022c6..4de60e96a0bf8 100644 --- a/src/wp-includes/blocks.php +++ b/src/wp-includes/blocks.php @@ -328,14 +328,17 @@ function register_block_script_handle( $metadata, $field_name, $index = 0 ) { /** * Finds a style handle for the block metadata field. * - * Detects when a path to a file was provided and registers the style under an - * automatically generated handle name. It returns the unprocessed style handle + * Detects when a path to a file was provided and optionally finds a + * corresponding asset file with details necessary to register the style. The + * handle is taken from the asset file when it provides one, and is otherwise + * generated automatically. It returns the unprocessed style handle * otherwise, except for the first style of a core block, which is instead * registered from the block's own stylesheet when separate core block assets * are loaded. Core blocks accept only handles, not paths. * * @since 5.5.0 * @since 6.1.0 Added `$index` parameter. + * @since 7.2.0 Added support for asset files (`.asset.php`) providing custom handle, dependencies, and version. * * @param array $metadata Block metadata. * @param string $field_name Field name to pick from metadata. @@ -370,12 +373,6 @@ function register_block_style_handle( $metadata, $field_name, $index = 0 ) { $style_handle = $style_handle[ $index ]; } - $style_handle_name = generate_block_asset_handle( $metadata['name'], $field_name, $index ); - // If the style handle is already registered, skip re-registering. - if ( wp_style_is( $style_handle_name, 'registered' ) ) { - return $style_handle_name; - } - static $wpinc_path_norm = ''; if ( ! $wpinc_path_norm ) { $wpinc_path_norm = wp_normalize_path( realpath( ABSPATH . WPINC ) ); @@ -393,6 +390,7 @@ function register_block_style_handle( $metadata, $field_name, $index = 0 ) { if ( $is_core_block && ! $is_style_handle ) { return false; } + // Return the style handle unless it's the first item for every core block that requires special treatment. if ( $is_style_handle && ! ( $is_core_block && 0 === $index ) ) { return $style_handle; @@ -404,15 +402,39 @@ function register_block_style_handle( $metadata, $field_name, $index = 0 ) { $style_path = ( 'editorStyle' === $field_name ) ? "editor{$suffix}.css" : "style{$suffix}.css"; } - $style_path_norm = wp_normalize_path( realpath( dirname( $metadata['file'] ) . '/' . $style_path ) ); - $style_uri = get_block_asset_url( $style_path_norm ); + $path = isset( $metadata['file'] ) ? dirname( $metadata['file'] ) : ''; + $style_asset_path = ''; + $style_asset = array(); + if ( ! $is_core_block && '' !== $path && str_ends_with( $style_path, '.css' ) ) { + $style_asset_raw_path = $path . '/' . substr_replace( $style_path, '.asset.php', - strlen( '.css' ) ); + $style_asset_path = wp_normalize_path( + realpath( $style_asset_raw_path ) + ); + + // Asset file for blocks is optional. See https://core.trac.wordpress.org/ticket/60460. + /** @var array{ handle?: non-falsy-string, dependencies?: list, version?: string|false|null, ... } $style_asset */ + $style_asset = ! empty( $style_asset_path ) ? require $style_asset_path : array(); + } + + $style_handle_name = $style_asset['handle'] ?? + generate_block_asset_handle( $metadata['name'], $field_name, $index ); + + // If the style handle is already registered, skip re-registering. + if ( wp_style_is( $style_handle_name, 'registered' ) ) { + return $style_handle_name; + } + + $style_path_norm = wp_normalize_path( realpath( $path . '/' . $style_path ) ); + $style_uri = get_block_asset_url( $style_path_norm ); + $style_dependencies = $style_asset['dependencies'] ?? array(); + $block_version = ! $is_core_block && isset( $metadata['version'] ) ? $metadata['version'] : false; + $auto_version = $style_path_norm && defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? filemtime( $style_path_norm ) : $block_version; + $version = $style_asset['version'] ?? $auto_version; - $block_version = ! $is_core_block && isset( $metadata['version'] ) ? $metadata['version'] : false; - $version = $style_path_norm && defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? filemtime( $style_path_norm ) : $block_version; - $result = wp_register_style( + $result = wp_register_style( $style_handle_name, $style_uri, - array(), + $style_dependencies, $version ); if ( ! $result ) { diff --git a/tests/phpunit/data/blocks/notice/shared-style.asset.php b/tests/phpunit/data/blocks/notice/shared-style.asset.php new file mode 100644 index 0000000000000..676021442a517 --- /dev/null +++ b/tests/phpunit/data/blocks/notice/shared-style.asset.php @@ -0,0 +1,7 @@ + 'tests-my-shared-style', + 'dependencies' => array( 'wp-components' ), + 'version' => 'test-style-version', +); diff --git a/tests/phpunit/data/blocks/notice/shared-style.css b/tests/phpunit/data/blocks/notice/shared-style.css new file mode 100644 index 0000000000000..323592165fa92 --- /dev/null +++ b/tests/phpunit/data/blocks/notice/shared-style.css @@ -0,0 +1,3 @@ +.wp-block-notice { + color: red; +} diff --git a/tests/phpunit/tests/blocks/register.php b/tests/phpunit/tests/blocks/register.php index 1901d0ccf6702..7f03088f631b5 100644 --- a/tests/phpunit/tests/blocks/register.php +++ b/tests/phpunit/tests/blocks/register.php @@ -846,6 +846,84 @@ public function test_success_register_block_style_handle() { ); } + /** + * Tests registering a block style handle using an asset file with custom handle name, dependencies, and version. + * + * @covers ::register_block_style_handle + */ + public function test_success_register_block_style_handle_with_custom_handle_name() { + $custom_style_handle = 'tests-my-shared-style'; + $metadata = array( + 'file' => DIR_TESTDATA . '/blocks/notice/block.json', + 'name' => 'tests/sample-block', + 'style' => 'file:./shared-style.css', + ); + $result = register_block_style_handle( $metadata, 'style' ); + + $this->assertSame( $custom_style_handle, $result ); + $this->assertTrue( wp_style_is( $custom_style_handle, 'registered' ) ); + $this->assertStringEndsWith( + 'shared-style.css', + wp_styles()->registered[ $custom_style_handle ]->src + ); + $this->assertSame( + array( 'wp-components' ), + wp_styles()->registered[ $custom_style_handle ]->deps + ); + $this->assertSame( + 'test-style-version', + wp_styles()->registered[ $custom_style_handle ]->ver + ); + } + + /** + * Tests reusing an already-registered block style handle when custom handle name matches. + * + * @covers ::register_block_style_handle + */ + public function test_reuse_registered_block_style_handle_with_custom_handle_name() { + $custom_style_handle = 'tests-my-shared-style'; + $custom_style_src = 'https://example.com/foo.css'; + wp_register_style( $custom_style_handle, $custom_style_src ); + + $this->assertTrue( + wp_style_is( $custom_style_handle, 'registered' ) + ); + + $metadata = array( + 'file' => DIR_TESTDATA . '/blocks/notice/block.json', + 'name' => 'tests/sample-block', + 'style' => 'file:./shared-style.css', + ); + $result = register_block_style_handle( $metadata, 'style' ); + + $this->assertSame( $custom_style_handle, $result ); + $this->assertSame( + $custom_style_src, + wp_styles()->registered[ $custom_style_handle ]->src + ); + } + + /** + * Tests registering a block style handle with version from asset file. + * + * @covers ::register_block_style_handle + */ + public function test_register_block_style_handle_version_from_asset_file() { + $metadata = array( + 'file' => DIR_TESTDATA . '/blocks/notice/block.json', + 'name' => 'tests/version-test-block', + 'style' => 'file:./block.css', + ); + $result = register_block_style_handle( $metadata, 'style' ); + + $this->assertSame( 'tests-version-test-block-style', $result ); + $this->assertSame( + 'test', + wp_styles()->registered[ $result ]->ver + ); + } + /** * Tests that register_block_style_handle() loads RTL stylesheets when an RTL locale is set. *