From df35a2e50ed50aa61004c18e679f03d9d7573838 Mon Sep 17 00:00:00 2001 From: Grzegorz Ziolkowski Date: Wed, 30 Aug 2023 13:35:04 +0200 Subject: [PATCH] Blocks: Allow reading the script handle from asset files --- src/wp-includes/blocks.php | 41 +++-- .../blocks/notice/shared-script.asset.php | 7 + .../data/blocks/notice/shared-script.js | 1 + tests/phpunit/tests/blocks/register.php | 150 ++++++++++++------ 4 files changed, 130 insertions(+), 69 deletions(-) create mode 100644 tests/phpunit/data/blocks/notice/shared-script.asset.php create mode 100644 tests/phpunit/data/blocks/notice/shared-script.js diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php index 47620d7f808fc..7f88372f0f7c1 100644 --- a/src/wp-includes/blocks.php +++ b/src/wp-includes/blocks.php @@ -191,7 +191,7 @@ function register_block_script_module_id( $metadata, $field_name, $index = 0 ) { * * @since 5.5.0 * @since 6.1.0 Added `$index` parameter. - * @since 6.5.0 The asset file is optional. + * @since 6.5.0 The asset file is optional. Added script handle support in the asset file. * * @param array $metadata Block metadata. * @param string $field_name Field name to pick from metadata. @@ -205,42 +205,49 @@ function register_block_script_handle( $metadata, $field_name, $index = 0 ) { return false; } - $script_handle = $metadata[ $field_name ]; - if ( is_array( $script_handle ) ) { - if ( empty( $script_handle[ $index ] ) ) { + $script_handle_or_path = $metadata[ $field_name ]; + if ( is_array( $script_handle_or_path ) ) { + if ( empty( $script_handle_or_path[ $index ] ) ) { return false; } - $script_handle = $script_handle[ $index ]; + $script_handle_or_path = $script_handle_or_path[ $index ]; } - $script_path = remove_block_asset_path_prefix( $script_handle ); - if ( $script_handle === $script_path ) { - return $script_handle; + $script_path = remove_block_asset_path_prefix( $script_handle_or_path ); + if ( $script_handle_or_path === $script_path ) { + return $script_handle_or_path; } $path = dirname( $metadata['file'] ); $script_asset_raw_path = $path . '/' . substr_replace( $script_path, '.asset.php', - strlen( '.js' ) ); - $script_handle = generate_block_asset_handle( $metadata['name'], $field_name, $index ); $script_asset_path = wp_normalize_path( realpath( $script_asset_raw_path ) ); - $script_path_norm = wp_normalize_path( realpath( $path . '/' . $script_path ) ); - $script_uri = get_block_asset_url( $script_path_norm ); + // Asset file for blocks is optional. See https://core.trac.wordpress.org/ticket/60460. + $script_asset = ! empty( $script_asset_path ) ? require $script_asset_path : array(); + $script_handle = isset( $script_asset['handle'] ) ? + $script_asset['handle'] : + generate_block_asset_handle( $metadata['name'], $field_name, $index ); + if ( wp_script_is( $script_handle, 'registered' ) ) { + return $script_handle; + } - $script_args = array(); + $script_path_norm = wp_normalize_path( realpath( $path . '/' . $script_path ) ); + $script_uri = get_block_asset_url( $script_path_norm ); + $script_dependencies = isset( $script_asset['dependencies'] ) ? $script_asset['dependencies'] : array(); + $block_version = isset( $metadata['version'] ) ? $metadata['version'] : false; + $script_version = isset( $script_asset['version'] ) ? $script_asset['version'] : $block_version; + $script_args = array(); if ( 'viewScript' === $field_name && $script_uri ) { $script_args['strategy'] = 'defer'; } - // Asset file for blocks is optional. See https://core.trac.wordpress.org/ticket/60460. - $script_asset = ! empty( $script_asset_path ) ? require $script_asset_path : array(); - $script_dependencies = isset( $script_asset['dependencies'] ) ? $script_asset['dependencies'] : array(); - $result = wp_register_script( + $result = wp_register_script( $script_handle, $script_uri, $script_dependencies, - isset( $script_asset['version'] ) ? $script_asset['version'] : false, + $script_version, $script_args ); if ( ! $result ) { diff --git a/tests/phpunit/data/blocks/notice/shared-script.asset.php b/tests/phpunit/data/blocks/notice/shared-script.asset.php new file mode 100644 index 0000000000000..d35471c73db2a --- /dev/null +++ b/tests/phpunit/data/blocks/notice/shared-script.asset.php @@ -0,0 +1,7 @@ + 'tests-my-shared-script', + 'dependencies' => array(), + 'version' => 'test', +); diff --git a/tests/phpunit/data/blocks/notice/shared-script.js b/tests/phpunit/data/blocks/notice/shared-script.js new file mode 100644 index 0000000000000..a9abbdbcc3d20 --- /dev/null +++ b/tests/phpunit/data/blocks/notice/shared-script.js @@ -0,0 +1 @@ +/* Another test JavaScript file. */ diff --git a/tests/phpunit/tests/blocks/register.php b/tests/phpunit/tests/blocks/register.php index 7ac046f147955..6263515375cf1 100644 --- a/tests/phpunit/tests/blocks/register.php +++ b/tests/phpunit/tests/blocks/register.php @@ -52,16 +52,17 @@ public function render_stub() {} * @since 5.0.0 */ public function tear_down() { - $registry = WP_Block_Type_Registry::get_instance(); - - foreach ( array( 'core/test-static', 'core/test-dynamic', 'tests/notice' ) as $block_name ) { - if ( $registry->is_registered( $block_name ) ) { - $registry->unregister( $block_name ); + // Removes test block types registered by test cases. + $block_types = WP_Block_Type_Registry::get_instance()->get_all_registered(); + foreach ( $block_types as $block_type ) { + $block_name = $block_type->name; + if ( str_starts_with( $block_name, 'tests/' ) ) { + unregister_block_type( $block_name ); } } foreach ( wp_scripts()->registered as $script_handle => $script ) { - if ( str_starts_with( $script_handle, 'unit-tests-' ) ) { + if ( str_starts_with( $script_handle, 'tests-' ) ) { wp_deregister_script( $script_handle ); } } @@ -82,7 +83,7 @@ public function filter_set_locale_to_polish() { * @ticket 45109 */ public function test_register_affects_main_registry() { - $name = 'core/test-static'; + $name = 'tests/static'; $settings = array( 'icon' => 'text', ); @@ -97,7 +98,7 @@ public function test_register_affects_main_registry() { * @ticket 45109 */ public function test_unregister_affects_main_registry() { - $name = 'core/test-static'; + $name = 'tests/static'; $settings = array( 'icon' => 'text', ); @@ -141,43 +142,43 @@ public function test_removes_block_asset_path_prefix_and_current_directory() { * @ticket 60233 */ public function test_generate_block_asset_handle() { - $block_name = 'unit-tests/my-block'; + $block_name = 'tests/my-block'; $this->assertSame( - 'unit-tests-my-block-editor-script', + 'tests-my-block-editor-script', generate_block_asset_handle( $block_name, 'editorScript' ) ); $this->assertSame( - 'unit-tests-my-block-script', + 'tests-my-block-script', generate_block_asset_handle( $block_name, 'script', 0 ) ); $this->assertSame( - 'unit-tests-my-block-view-script-100', + 'tests-my-block-view-script-100', generate_block_asset_handle( $block_name, 'viewScript', 99 ) ); $this->assertSame( - 'unit-tests-my-block-view-script-module', + 'tests-my-block-view-script-module', generate_block_asset_handle( $block_name, 'viewScriptModule' ) ); $this->assertSame( - 'unit-tests-my-block-view-script-module-2', + 'tests-my-block-view-script-module-2', generate_block_asset_handle( $block_name, 'viewScriptModule', 1 ) ); $this->assertSame( - 'unit-tests-my-block-view-script-module-100', + 'tests-my-block-view-script-module-100', generate_block_asset_handle( $block_name, 'viewScriptModule', 99 ) ); $this->assertSame( - 'unit-tests-my-block-editor-style-2', + 'tests-my-block-editor-style-2', generate_block_asset_handle( $block_name, 'editorStyle', 1 ) ); $this->assertSame( - 'unit-tests-my-block-style', + 'tests-my-block-style', generate_block_asset_handle( $block_name, 'style' ) ); // @ticket 59673 $this->assertSame( - 'unit-tests-my-block-view-style', + 'tests-my-block-view-style', generate_block_asset_handle( $block_name, 'viewStyle' ), 'asset handle for viewStyle is not generated correctly' ); @@ -335,12 +336,12 @@ public function test_wrong_array_index_do_not_register_block_script_module_id() public function test_missing_asset_file_register_block_script_module_id() { $metadata = array( 'file' => __FILE__, - 'name' => 'unit-tests/test-block', + 'name' => 'tests/test-block', 'viewScriptModule' => 'file:./blocks/notice/missing-asset.js', ); $result = register_block_script_module_id( $metadata, 'viewScriptModule' ); - $this->assertSame( 'unit-tests-test-block-view-script-module', $result ); + $this->assertSame( 'tests-test-block-view-script-module', $result ); } /** @@ -376,14 +377,14 @@ public function test_handles_passed_register_block_script_module_ids() { public function test_success_register_block_script_module_id() { $metadata = array( 'file' => DIR_TESTDATA . '/blocks/notice/block.json', - 'name' => 'unit-tests/test-block', + 'name' => 'tests/test-block', 'viewScriptModule' => 'file:./block.js', ); $result = register_block_script_module_id( $metadata, 'viewScriptModule' ); - $this->assertSame( 'unit-tests-test-block-view-script-module', $result ); + $this->assertSame( 'tests-test-block-view-script-module', $result ); - // Test the behavior directly within the unit test + // Test the behavior directly within the unit test. $this->assertFalse( strpos( wp_normalize_path( realpath( dirname( $metadata['file'] ) . '/' . $metadata['viewScriptModule'] ) ), @@ -430,12 +431,12 @@ public function test_handles_passed_register_block_script_handles() { public function test_missing_asset_file_register_block_script_handle_with_default_settings() { $metadata = array( 'file' => __FILE__, - 'name' => 'unit-tests/test-block', + 'name' => 'tests/test-block', 'script' => 'file:./blocks/notice/missing-asset.js', ); $result = register_block_script_handle( $metadata, 'script' ); - $this->assertSame( 'unit-tests-test-block-script', $result ); + $this->assertSame( 'tests-test-block-script', $result ); } /** @@ -444,14 +445,14 @@ public function test_missing_asset_file_register_block_script_handle_with_defaul public function test_success_register_block_script_handle() { $metadata = array( 'file' => DIR_TESTDATA . '/blocks/notice/block.json', - 'name' => 'unit-tests/test-block', + 'name' => 'tests/test-block', 'script' => 'file:./block.js', ); $result = register_block_script_handle( $metadata, 'script' ); - $this->assertSame( 'unit-tests-test-block-script', $result ); + $this->assertSame( 'tests-test-block-script', $result ); - // Test the behavior directly within the unit test + // Test the behavior directly within the unit test. $this->assertFalse( strpos( wp_normalize_path( realpath( dirname( $metadata['file'] ) . '/' . $metadata['script'] ) ), @@ -467,6 +468,51 @@ public function test_success_register_block_script_handle() { ); } + /** + * @ticket TBD... + */ + public function test_success_register_block_script_handle_with_custom_handle_name() { + $custom_script_handle = 'tests-my-shared-script'; + $metadata = array( + 'file' => DIR_TESTDATA . '/blocks/notice/block.json', + 'name' => 'tests/sample-block', + 'script' => 'file:./shared-script.js', + ); + $result = register_block_script_handle( $metadata, 'script' ); + + $this->assertSame( $custom_script_handle, $result ); + $this->assertStringEndsWith( + 'shared-script.js', + wp_scripts()->registered[ $custom_script_handle ]->src + ); + } + + /** + * @ticket TBD... + */ + public function test_reuse_registered_block_script_handle_with_custom_handle_name() { + $custom_script_handle = 'tests-my-shared-script'; + $custom_script_src = 'https://example.com/foo.js'; + wp_register_script( $custom_script_handle, $custom_script_src ); + + $this->assertTrue( + wp_script_is( $custom_script_handle, 'registered' ) + ); + + $metadata = array( + 'file' => DIR_TESTDATA . '/blocks/notice/block.json', + 'name' => 'tests/sample-block', + 'script' => 'file:./shared-script.js', + ); + $result = register_block_script_handle( $metadata, 'script' ); + + $this->assertSame( $custom_script_handle, $result ); + $this->assertSame( + $custom_script_src, + wp_scripts()->registered[ $custom_script_handle ]->src + ); + } + /** * @ticket 55513 */ @@ -620,33 +666,33 @@ public function test_handles_passed_register_block_style_handles() { public function test_success_register_block_style_handle() { $metadata = array( 'file' => DIR_TESTDATA . '/blocks/notice/block.json', - 'name' => 'unit-tests/test-block', + 'name' => 'tests/test-block', 'style' => 'file:./block.css', 'viewStyle' => 'file:./block-view.css', ); $result = register_block_style_handle( $metadata, 'style' ); - $this->assertSame( 'unit-tests-test-block-style', $result ); - $this->assertFalse( wp_styles()->get_data( 'unit-tests-test-block-style', 'rtl' ) ); + $this->assertSame( 'tests-test-block-style', $result ); + $this->assertFalse( wp_styles()->get_data( 'tests-test-block-style', 'rtl' ) ); // @ticket 50328 $this->assertSame( wp_normalize_path( realpath( DIR_TESTDATA . '/blocks/notice/block.css' ) ), - wp_normalize_path( wp_styles()->get_data( 'unit-tests-test-block-style', 'path' ) ) + wp_normalize_path( wp_styles()->get_data( 'tests-test-block-style', 'path' ) ) ); // Test viewStyle property $result = register_block_style_handle( $metadata, 'viewStyle' ); - $this->assertSame( 'unit-tests-test-block-view-style', $result ); + $this->assertSame( 'tests-test-block-view-style', $result ); // @ticket 59673 $this->assertSame( wp_normalize_path( realpath( DIR_TESTDATA . '/blocks/notice/block-view.css' ) ), - wp_normalize_path( wp_styles()->get_data( 'unit-tests-test-block-view-style', 'path' ) ), + wp_normalize_path( wp_styles()->get_data( 'tests-test-block-view-style', 'path' ) ), 'viewStyle asset path is not correct' ); - // Test the behavior directly within the unit test + // Test the behavior directly within the unit test. $this->assertFalse( strpos( wp_normalize_path( realpath( dirname( $metadata['file'] ) . '/' . $metadata['style'] ) ), @@ -675,7 +721,7 @@ public function test_register_block_style_handle_should_load_rtl_stylesheets_for $metadata = array( 'file' => DIR_TESTDATA . '/blocks/notice/block.json', - 'name' => 'unit-tests/test-block-rtl', + 'name' => 'tests/test-block-rtl', 'style' => 'file:./block.css', ); @@ -683,14 +729,14 @@ public function test_register_block_style_handle_should_load_rtl_stylesheets_for $wp_locale->text_direction = 'rtl'; $handle = register_block_style_handle( $metadata, 'style' ); - $extra_rtl = wp_styles()->get_data( 'unit-tests-test-block-rtl-style', 'rtl' ); - $extra_suffix = wp_styles()->get_data( 'unit-tests-test-block-rtl-style', 'suffix' ); - $extra_path = wp_normalize_path( wp_styles()->get_data( 'unit-tests-test-block-rtl-style', 'path' ) ); + $extra_rtl = wp_styles()->get_data( 'tests-test-block-rtl-style', 'rtl' ); + $extra_suffix = wp_styles()->get_data( 'tests-test-block-rtl-style', 'suffix' ); + $extra_path = wp_normalize_path( wp_styles()->get_data( 'tests-test-block-rtl-style', 'path' ) ); $wp_locale->text_direction = $orig_text_dir; $this->assertSame( - 'unit-tests-test-block-rtl-style', + 'tests-test-block-rtl-style', $handle, 'The handle did not match the expected handle.' ); @@ -720,13 +766,13 @@ public function test_register_block_style_handle_should_load_rtl_stylesheets_for public function test_register_nonexistent_stylesheet() { $metadata = array( 'file' => DIR_TESTDATA . '/blocks/notice/block.json', - 'name' => 'unit-tests/test-block-nonexistent-stylesheet', + 'name' => 'tests/test-block-nonexistent-stylesheet', 'style' => 'file:./nonexistent.css', ); register_block_style_handle( $metadata, 'style' ); global $wp_styles; - $this->assertFalse( $wp_styles->registered['unit-tests-test-block-nonexistent-stylesheet-style']->src ); + $this->assertFalse( $wp_styles->registered['tests-test-block-nonexistent-stylesheet-style']->src ); } /** @@ -1044,13 +1090,13 @@ public function test_block_registers_with_metadata_fixture() { // @ticket 50328 $this->assertSame( wp_normalize_path( realpath( DIR_TESTDATA . '/blocks/notice/block.css' ) ), - wp_normalize_path( wp_styles()->get_data( 'unit-tests-test-block-style', 'path' ) ) + wp_normalize_path( wp_styles()->get_data( 'tests-test-block-style', 'path' ) ) ); // @ticket 59673 $this->assertSame( wp_normalize_path( realpath( DIR_TESTDATA . '/blocks/notice/block-view.css' ) ), - wp_normalize_path( wp_styles()->get_data( 'unit-tests-test-block-view-style', 'path' ) ), + wp_normalize_path( wp_styles()->get_data( 'tests-test-block-view-style', 'path' ) ), 'viewStyle asset path is not correct' ); @@ -1089,10 +1135,10 @@ public function test_block_register_block_type_proxy_for_metadata() { */ public function test_register_block_type_accepts_editor_script_array( $editor_script, $expected ) { $settings = array( 'editor_script' => $editor_script ); - register_block_type( 'core/test-static', $settings ); + register_block_type( 'tests/static', $settings ); $registry = WP_Block_Type_Registry::get_instance(); - $block_type = $registry->get_registered( 'core/test-static' ); + $block_type = $registry->get_registered( 'tests/static' ); $this->assertObjectHasProperty( 'editor_script_handles', $block_type ); $actual_script = $block_type->editor_script; $actual_script_handles = $block_type->editor_script_handles; @@ -1155,10 +1201,10 @@ public function data_register_block_type_accepts_editor_script_array() { */ public function test_register_block_type_throws_doing_it_wrong( $editor_script, $expected ) { $settings = array( 'editor_script' => $editor_script ); - register_block_type( 'core/test-static', $settings ); + register_block_type( 'tests/static', $settings ); $registry = WP_Block_Type_Registry::get_instance(); - $block_type = $registry->get_registered( 'core/test-static' ); + $block_type = $registry->get_registered( 'tests/static' ); $this->assertObjectHasProperty( 'editor_script_handles', $block_type ); $actual_script = $block_type->editor_script; $actual_script_handles = $block_type->editor_script_handles; @@ -1248,13 +1294,13 @@ public function test_block_registers_with_metadata_i18n_support() { * @ticket 45109 */ public function test_get_dynamic_block_names() { - register_block_type( 'core/test-static', array() ); - register_block_type( 'core/test-dynamic', array( 'render_callback' => array( $this, 'render_stub' ) ) ); + register_block_type( 'tests/static', array() ); + register_block_type( 'tests/dynamic', array( 'render_callback' => array( $this, 'render_stub' ) ) ); $dynamic_block_names = get_dynamic_block_names(); - $this->assertContains( 'core/test-dynamic', $dynamic_block_names ); - $this->assertNotContains( 'core/test-static', $dynamic_block_names ); + $this->assertContains( 'tests/dynamic', $dynamic_block_names ); + $this->assertNotContains( 'tests/static', $dynamic_block_names ); } /**