From 691cdf51309a6181df1c6ec1ce9b48628f9fd340 Mon Sep 17 00:00:00 2001 From: Aki Hamano Date: Sat, 14 Feb 2026 22:10:57 +0900 Subject: [PATCH 01/20] Allow PHP-Only Block Registration --- src/wp-includes/block-editor.php | 10 +- .../block-supports/auto-register.php | 56 +++++++++ src/wp-settings.php | 1 + .../tests/block-supports/auto-register.php | 108 ++++++++++++++++++ tests/phpunit/tests/blocks/editor.php | 36 ++++++ 5 files changed, 208 insertions(+), 3 deletions(-) create mode 100644 src/wp-includes/block-supports/auto-register.php create mode 100644 tests/phpunit/tests/block-supports/auto-register.php diff --git a/src/wp-includes/block-editor.php b/src/wp-includes/block-editor.php index af873178eb7aa..858c747a3f660 100644 --- a/src/wp-includes/block-editor.php +++ b/src/wp-includes/block-editor.php @@ -497,10 +497,14 @@ function get_block_editor_settings( array $custom_settings, $block_editor_contex ); $editor_settings['__experimentalBlockBindingsSupportedAttributes'] = array(); - foreach ( array_keys( WP_Block_Type_Registry::get_instance()->get_all_registered() ) as $block_type ) { - $supported_block_attributes = get_block_bindings_supported_attributes( $block_type ); + $editor_settings['autoRegisterBlocks'] = array(); + foreach ( WP_Block_Type_Registry::get_instance()->get_all_registered() as $block_name => $block_type ) { + $supported_block_attributes = get_block_bindings_supported_attributes( $block_name ); if ( ! empty( $supported_block_attributes ) ) { - $editor_settings['__experimentalBlockBindingsSupportedAttributes'][ $block_type ] = $supported_block_attributes; + $editor_settings['__experimentalBlockBindingsSupportedAttributes'][ $block_name ] = $supported_block_attributes; + } + if ( ! empty( $block_type->supports['auto_register'] ) && ! empty( $block_type->render_callback ) ) { + $editor_settings['autoRegisterBlocks'][] = $block_name; } } diff --git a/src/wp-includes/block-supports/auto-register.php b/src/wp-includes/block-supports/auto-register.php new file mode 100644 index 0000000000000..21c5b30da2f4c --- /dev/null +++ b/src/wp-includes/block-supports/auto-register.php @@ -0,0 +1,56 @@ + $def ) { + // Skip HTML-derived attributes (edited inline, not via inspector). + if ( ! empty( $def['source'] ) ) { + continue; + } + // Skip internal attributes (not user-configurable). + if ( isset( $def['role'] ) && 'local' === $def['role'] ) { + continue; + } + $args['attributes'][ $name ]['autoGenerateControl'] = true; + } + + return $args; +} + +// Priority 5 to mark original attributes before other filters (priority 10+) might add their own. +add_filter( 'register_block_type_args', 'wp_mark_auto_generate_control_attributes', 5, 2 ); diff --git a/src/wp-settings.php b/src/wp-settings.php index 60c220100f539..3257d1014b752 100644 --- a/src/wp-settings.php +++ b/src/wp-settings.php @@ -410,6 +410,7 @@ require ABSPATH . WPINC . '/block-supports/background.php'; require ABSPATH . WPINC . '/block-supports/block-style-variations.php'; require ABSPATH . WPINC . '/block-supports/aria-label.php'; +require ABSPATH . WPINC . '/block-supports/auto-register.php'; require ABSPATH . WPINC . '/block-supports/anchor.php'; require ABSPATH . WPINC . '/block-supports/block-visibility.php'; require ABSPATH . WPINC . '/style-engine.php'; diff --git a/tests/phpunit/tests/block-supports/auto-register.php b/tests/phpunit/tests/block-supports/auto-register.php new file mode 100644 index 0000000000000..931a6fb2674b4 --- /dev/null +++ b/tests/phpunit/tests/block-supports/auto-register.php @@ -0,0 +1,108 @@ + array( 'auto_register' => true ), + 'attributes' => array( + 'title' => array( 'type' => 'string' ), + 'count' => array( 'type' => 'integer' ), + ), + ); + + $result = wp_mark_auto_generate_control_attributes( $settings, 'test/block' ); + + $this->assertTrue( $result['attributes']['title']['autoGenerateControl'] ); + $this->assertTrue( $result['attributes']['count']['autoGenerateControl'] ); + } + + /** + * Tests that attributes are not marked without auto_register flag. + * + * @ticket 64639 + */ + public function test_does_not_mark_attributes_without_auto_register() { + $settings = array( + 'attributes' => array( + 'title' => array( 'type' => 'string' ), + ), + ); + + $result = wp_mark_auto_generate_control_attributes( $settings, 'test/block' ); + + $this->assertArrayNotHasKey( 'autoGenerateControl', $result['attributes']['title'] ); + } + + /** + * Tests that attributes with source are excluded. + * + * @ticket 64639 + */ + public function test_excludes_attributes_with_source() { + $settings = array( + 'supports' => array( 'auto_register' => true ), + 'attributes' => array( + 'title' => array( 'type' => 'string' ), + 'content' => array( + 'type' => 'string', + 'source' => 'html', + ), + ), + ); + + $result = wp_mark_auto_generate_control_attributes( $settings, 'test/block' ); + + $this->assertTrue( $result['attributes']['title']['autoGenerateControl'] ); + $this->assertArrayNotHasKey( 'autoGenerateControl', $result['attributes']['content'] ); + } + + /** + * Tests that attributes with role: local are excluded. + * + * Example: The 'blob' attribute in media blocks (image, video, file, audio) + * stores a temporary blob URL during file upload. This is internal state + * that shouldn't be shown in the inspector or saved to the database. + * + * @ticket 64639 + */ + public function test_excludes_attributes_with_role_local() { + $settings = array( + 'supports' => array( 'auto_register' => true ), + 'attributes' => array( + 'title' => array( 'type' => 'string' ), + 'blob' => array( + 'type' => 'string', + 'role' => 'local', + ), + ), + ); + + $result = wp_mark_auto_generate_control_attributes( $settings, 'test/block' ); + + $this->assertTrue( $result['attributes']['title']['autoGenerateControl'] ); + $this->assertArrayNotHasKey( 'autoGenerateControl', $result['attributes']['blob'] ); + } + + /** + * Tests that empty attributes are handled gracefully. + */ + public function test_handles_empty_attributes() { + $settings = array( + 'supports' => array( 'auto_register' => true ), + ); + + $result = wp_mark_auto_generate_control_attributes( $settings, 'test/block' ); + + $this->assertSame( $settings, $result ); + } +} diff --git a/tests/phpunit/tests/blocks/editor.php b/tests/phpunit/tests/blocks/editor.php index 4241161388eb8..1c6696a8593ec 100644 --- a/tests/phpunit/tests/blocks/editor.php +++ b/tests/phpunit/tests/blocks/editor.php @@ -709,6 +709,42 @@ public function test_get_classic_theme_supports_block_editor_settings() { ); } + /** + * @ticket 64639 + */ + public function test_get_block_editor_settings_auto_register_blocks() { + $block_default = 'test/default'; + $block_with_render = 'test/auto-register-with-render'; + $block_without_render = 'test/auto-register-without-render'; + + register_block_type( + $block_default, + array() + ); + register_block_type( + $block_with_render, + array( + 'supports' => array( 'auto_register' => true ), + 'render_callback' => '__return_empty_string', + ) + ); + register_block_type( + $block_without_render, + array( + 'supports' => array( 'auto_register' => true ), + ) + ); + + $post_editor_context = new WP_Block_Editor_Context( array( 'post' => get_post() ) ); + $settings = get_block_editor_settings( array(), $post_editor_context ); + + unregister_block_type( $block_default ); + unregister_block_type( $block_with_render ); + unregister_block_type( $block_without_render ); + + $this->assertSame( array( $block_with_render ), $settings['autoRegisterBlocks'] ); + } + /** * Data provider. * From d1c5a3abffb9ca5396d02e1456455eb1f1d2e64a Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Sun, 15 Feb 2026 16:17:26 +0900 Subject: [PATCH 02/20] Improve PHPDoc Co-authored-by: Weston Ruter --- src/wp-includes/block-supports/auto-register.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wp-includes/block-supports/auto-register.php b/src/wp-includes/block-supports/auto-register.php index 21c5b30da2f4c..30fdc5ed9d799 100644 --- a/src/wp-includes/block-supports/auto-register.php +++ b/src/wp-includes/block-supports/auto-register.php @@ -23,9 +23,9 @@ * @since 7.0.0 * @access private * - * @param array $args Array of arguments for registering a block type. - * @param string $block_type Block type name including namespace. - * @return array Modified block type arguments. + * @param array $args Array of arguments for registering a block type. + * @param string $block_type Block type name including namespace. + * @return array Modified block type arguments. */ function wp_mark_auto_generate_control_attributes( array $args, string $block_type ): array { if ( empty( $args['attributes'] ) || ! is_array( $args['attributes'] ) ) { From 1cccbbc1c1f54edf79f49da18410906ed08a3376 Mon Sep 17 00:00:00 2001 From: Aki Hamano Date: Sun, 15 Feb 2026 16:22:08 +0900 Subject: [PATCH 03/20] Make variable names clearer --- src/wp-includes/block-supports/auto-register.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/wp-includes/block-supports/auto-register.php b/src/wp-includes/block-supports/auto-register.php index 30fdc5ed9d799..f7da96279746a 100644 --- a/src/wp-includes/block-supports/auto-register.php +++ b/src/wp-includes/block-supports/auto-register.php @@ -37,16 +37,16 @@ function wp_mark_auto_generate_control_attributes( array $args, string $block_ty return $args; } - foreach ( $args['attributes'] as $name => $def ) { + foreach ( $args['attributes'] as $attr_key => $attr_schema ) { // Skip HTML-derived attributes (edited inline, not via inspector). - if ( ! empty( $def['source'] ) ) { + if ( ! empty( $attr_schema['source'] ) ) { continue; } // Skip internal attributes (not user-configurable). - if ( isset( $def['role'] ) && 'local' === $def['role'] ) { + if ( isset( $attr_schema['role'] ) && 'local' === $attr_schema['role'] ) { continue; } - $args['attributes'][ $name ]['autoGenerateControl'] = true; + $args['attributes'][ $attr_key ]['autoGenerateControl'] = true; } return $args; From ac3ea46b26967de5366b6652f9deaba2929849e6 Mon Sep 17 00:00:00 2001 From: Aki Hamano Date: Sun, 15 Feb 2026 16:30:36 +0900 Subject: [PATCH 04/20] Removed unused second parameter --- src/wp-includes/block-supports/auto-register.php | 7 +++---- tests/phpunit/tests/block-supports/auto-register.php | 10 +++++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/wp-includes/block-supports/auto-register.php b/src/wp-includes/block-supports/auto-register.php index f7da96279746a..9f81724779d7f 100644 --- a/src/wp-includes/block-supports/auto-register.php +++ b/src/wp-includes/block-supports/auto-register.php @@ -23,11 +23,10 @@ * @since 7.0.0 * @access private * - * @param array $args Array of arguments for registering a block type. - * @param string $block_type Block type name including namespace. + * @param array $args Array of arguments for registering a block type. * @return array Modified block type arguments. */ -function wp_mark_auto_generate_control_attributes( array $args, string $block_type ): array { +function wp_mark_auto_generate_control_attributes( array $args ): array { if ( empty( $args['attributes'] ) || ! is_array( $args['attributes'] ) ) { return $args; } @@ -53,4 +52,4 @@ function wp_mark_auto_generate_control_attributes( array $args, string $block_ty } // Priority 5 to mark original attributes before other filters (priority 10+) might add their own. -add_filter( 'register_block_type_args', 'wp_mark_auto_generate_control_attributes', 5, 2 ); +add_filter( 'register_block_type_args', 'wp_mark_auto_generate_control_attributes', 5, 1 ); diff --git a/tests/phpunit/tests/block-supports/auto-register.php b/tests/phpunit/tests/block-supports/auto-register.php index 931a6fb2674b4..e3a2d9e2de2d2 100644 --- a/tests/phpunit/tests/block-supports/auto-register.php +++ b/tests/phpunit/tests/block-supports/auto-register.php @@ -20,7 +20,7 @@ public function test_marks_attributes_with_auto_register_flag() { ), ); - $result = wp_mark_auto_generate_control_attributes( $settings, 'test/block' ); + $result = wp_mark_auto_generate_control_attributes( $settings ); $this->assertTrue( $result['attributes']['title']['autoGenerateControl'] ); $this->assertTrue( $result['attributes']['count']['autoGenerateControl'] ); @@ -38,7 +38,7 @@ public function test_does_not_mark_attributes_without_auto_register() { ), ); - $result = wp_mark_auto_generate_control_attributes( $settings, 'test/block' ); + $result = wp_mark_auto_generate_control_attributes( $settings ); $this->assertArrayNotHasKey( 'autoGenerateControl', $result['attributes']['title'] ); } @@ -60,7 +60,7 @@ public function test_excludes_attributes_with_source() { ), ); - $result = wp_mark_auto_generate_control_attributes( $settings, 'test/block' ); + $result = wp_mark_auto_generate_control_attributes( $settings ); $this->assertTrue( $result['attributes']['title']['autoGenerateControl'] ); $this->assertArrayNotHasKey( 'autoGenerateControl', $result['attributes']['content'] ); @@ -87,7 +87,7 @@ public function test_excludes_attributes_with_role_local() { ), ); - $result = wp_mark_auto_generate_control_attributes( $settings, 'test/block' ); + $result = wp_mark_auto_generate_control_attributes( $settings ); $this->assertTrue( $result['attributes']['title']['autoGenerateControl'] ); $this->assertArrayNotHasKey( 'autoGenerateControl', $result['attributes']['blob'] ); @@ -101,7 +101,7 @@ public function test_handles_empty_attributes() { 'supports' => array( 'auto_register' => true ), ); - $result = wp_mark_auto_generate_control_attributes( $settings, 'test/block' ); + $result = wp_mark_auto_generate_control_attributes( $settings ); $this->assertSame( $settings, $result ); } From 0a7d27b881d9def37b173a88400a46f4e7f472ff Mon Sep 17 00:00:00 2001 From: Aki Hamano Date: Mon, 16 Feb 2026 20:53:03 +0900 Subject: [PATCH 05/20] Add new function to detect auto-registered blocks --- src/wp-includes/block-editor.php | 10 +++------- src/wp-includes/default-filters.php | 3 ++- src/wp-includes/script-loader.php | 27 +++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/wp-includes/block-editor.php b/src/wp-includes/block-editor.php index 858c747a3f660..af873178eb7aa 100644 --- a/src/wp-includes/block-editor.php +++ b/src/wp-includes/block-editor.php @@ -497,14 +497,10 @@ function get_block_editor_settings( array $custom_settings, $block_editor_contex ); $editor_settings['__experimentalBlockBindingsSupportedAttributes'] = array(); - $editor_settings['autoRegisterBlocks'] = array(); - foreach ( WP_Block_Type_Registry::get_instance()->get_all_registered() as $block_name => $block_type ) { - $supported_block_attributes = get_block_bindings_supported_attributes( $block_name ); + foreach ( array_keys( WP_Block_Type_Registry::get_instance()->get_all_registered() ) as $block_type ) { + $supported_block_attributes = get_block_bindings_supported_attributes( $block_type ); if ( ! empty( $supported_block_attributes ) ) { - $editor_settings['__experimentalBlockBindingsSupportedAttributes'][ $block_name ] = $supported_block_attributes; - } - if ( ! empty( $block_type->supports['auto_register'] ) && ! empty( $block_type->render_callback ) ) { - $editor_settings['autoRegisterBlocks'][] = $block_name; + $editor_settings['__experimentalBlockBindingsSupportedAttributes'][ $block_type ] = $supported_block_attributes; } } diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php index de0b374ef4b56..d04fef1314626 100644 --- a/src/wp-includes/default-filters.php +++ b/src/wp-includes/default-filters.php @@ -621,8 +621,9 @@ add_action( 'enqueue_block_editor_assets', 'enqueue_editor_block_styles_assets' ); add_action( 'enqueue_block_editor_assets', 'wp_enqueue_editor_block_directory_assets' ); add_action( 'enqueue_block_editor_assets', 'wp_enqueue_editor_format_library_assets' ); -add_action( 'enqueue_block_editor_assets', 'wp_enqueue_block_editor_script_modules' ); add_action( 'enqueue_block_editor_assets', 'wp_enqueue_global_styles_css_custom_properties' ); +add_action( 'enqueue_block_editor_assets', 'wp_enqueue_block_editor_script_modules' ); +add_action( 'enqueue_block_editor_assets', 'wp_enqueue_auto_register_blocks' ); add_action( 'wp_print_scripts', 'wp_just_in_time_script_localization' ); add_filter( 'print_scripts_array', 'wp_prototype_before_jquery' ); add_action( 'customize_controls_print_styles', 'wp_resource_hints', 1 ); diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index 4e9de5a0a7ed9..afd6fb965ce71 100644 --- a/src/wp-includes/script-loader.php +++ b/src/wp-includes/script-loader.php @@ -4133,3 +4133,30 @@ function wp_html_custom_data_attribute_name( string $js_dataset_name ): ?string return $html_name; } + +/** + * Expose blocks with auto_register flag for ServerSideRender in the editor. + * + * Detects blocks that have the auto_register flag set in their supports + * and passes them to JavaScript for auto-registration with ServerSideRender. + * + * @since 7.0.0 + */ +function wp_enqueue_auto_register_blocks() { + $auto_register_blocks = array(); + $registered_blocks = WP_Block_Type_Registry::get_instance()->get_all_registered(); + + foreach ( $registered_blocks as $block_name => $block_type ) { + if ( ! empty( $block_type->supports['auto_register'] ) && ! empty( $block_type->render_callback ) ) { + $auto_register_blocks[] = $block_name; + } + } + + if ( ! empty( $auto_register_blocks ) ) { + wp_add_inline_script( + 'wp-block-library', + sprintf( 'window.__unstableAutoRegisterBlocks = %s;', wp_json_encode( $auto_register_blocks ) ), + 'before' + ); + } +} From 423d10a2a582355d7bbae946aadd9d946f369718 Mon Sep 17 00:00:00 2001 From: Aki Hamano Date: Mon, 16 Feb 2026 20:54:07 +0900 Subject: [PATCH 06/20] Remove unnecessary unit test --- tests/phpunit/tests/blocks/editor.php | 36 --------------------------- 1 file changed, 36 deletions(-) diff --git a/tests/phpunit/tests/blocks/editor.php b/tests/phpunit/tests/blocks/editor.php index 1c6696a8593ec..4241161388eb8 100644 --- a/tests/phpunit/tests/blocks/editor.php +++ b/tests/phpunit/tests/blocks/editor.php @@ -709,42 +709,6 @@ public function test_get_classic_theme_supports_block_editor_settings() { ); } - /** - * @ticket 64639 - */ - public function test_get_block_editor_settings_auto_register_blocks() { - $block_default = 'test/default'; - $block_with_render = 'test/auto-register-with-render'; - $block_without_render = 'test/auto-register-without-render'; - - register_block_type( - $block_default, - array() - ); - register_block_type( - $block_with_render, - array( - 'supports' => array( 'auto_register' => true ), - 'render_callback' => '__return_empty_string', - ) - ); - register_block_type( - $block_without_render, - array( - 'supports' => array( 'auto_register' => true ), - ) - ); - - $post_editor_context = new WP_Block_Editor_Context( array( 'post' => get_post() ) ); - $settings = get_block_editor_settings( array(), $post_editor_context ); - - unregister_block_type( $block_default ); - unregister_block_type( $block_with_render ); - unregister_block_type( $block_without_render ); - - $this->assertSame( array( $block_with_render ), $settings['autoRegisterBlocks'] ); - } - /** * Data provider. * From c808f995545bbdd1f838b5efe75e01446010185c Mon Sep 17 00:00:00 2001 From: Aki Hamano Date: Mon, 16 Feb 2026 21:11:09 +0900 Subject: [PATCH 07/20] Rearrange order of action hooks --- src/wp-includes/default-filters.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php index d04fef1314626..1a5732ac708ab 100644 --- a/src/wp-includes/default-filters.php +++ b/src/wp-includes/default-filters.php @@ -621,8 +621,8 @@ add_action( 'enqueue_block_editor_assets', 'enqueue_editor_block_styles_assets' ); add_action( 'enqueue_block_editor_assets', 'wp_enqueue_editor_block_directory_assets' ); add_action( 'enqueue_block_editor_assets', 'wp_enqueue_editor_format_library_assets' ); -add_action( 'enqueue_block_editor_assets', 'wp_enqueue_global_styles_css_custom_properties' ); add_action( 'enqueue_block_editor_assets', 'wp_enqueue_block_editor_script_modules' ); +add_action( 'enqueue_block_editor_assets', 'wp_enqueue_global_styles_css_custom_properties' ); add_action( 'enqueue_block_editor_assets', 'wp_enqueue_auto_register_blocks' ); add_action( 'wp_print_scripts', 'wp_just_in_time_script_localization' ); add_filter( 'print_scripts_array', 'wp_prototype_before_jquery' ); From 4ede6ded3f3613c68b36e58ae5e4258f38df3dcd Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 17 Feb 2026 15:11:45 +0900 Subject: [PATCH 08/20] Make PHPDoc comment third-person Co-authored-by: Weston Ruter --- src/wp-includes/block-supports/auto-register.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/block-supports/auto-register.php b/src/wp-includes/block-supports/auto-register.php index 9f81724779d7f..187729933c996 100644 --- a/src/wp-includes/block-supports/auto-register.php +++ b/src/wp-includes/block-supports/auto-register.php @@ -7,7 +7,7 @@ */ /** - * Mark user-defined attributes for auto-generated inspector controls. + * Marks user-defined attributes for auto-generated inspector controls. * * This filter runs during block type registration, before the WP_Block_Type * is instantiated. Block supports add their attributes AFTER the block type From 723bd9b216f691cf9c9d9d778fcc8d8693582a97 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 17 Feb 2026 15:12:42 +0900 Subject: [PATCH 09/20] Add @see tag Co-authored-by: Weston Ruter --- src/wp-includes/block-supports/auto-register.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/block-supports/auto-register.php b/src/wp-includes/block-supports/auto-register.php index 187729933c996..5d655089efa2b 100644 --- a/src/wp-includes/block-supports/auto-register.php +++ b/src/wp-includes/block-supports/auto-register.php @@ -11,7 +11,7 @@ * * This filter runs during block type registration, before the WP_Block_Type * is instantiated. Block supports add their attributes AFTER the block type - * is created (via WP_Block_Supports::register_attributes()), so any attributes + * is created (via {@see WP_Block_Supports::register_attributes()}), so any attributes * present at this stage are user-defined. * * The marker tells generateFieldsFromAttributes() which attributes should From 936b6bfab4157ee5b9eb06d2a09578be22fe5004 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 17 Feb 2026 15:13:10 +0900 Subject: [PATCH 10/20] Make PHPDoc comment third-person Co-authored-by: Weston Ruter --- src/wp-includes/script-loader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index afd6fb965ce71..a091acd445d55 100644 --- a/src/wp-includes/script-loader.php +++ b/src/wp-includes/script-loader.php @@ -4135,7 +4135,7 @@ function wp_html_custom_data_attribute_name( string $js_dataset_name ): ?string } /** - * Expose blocks with auto_register flag for ServerSideRender in the editor. + * Exposes blocks with auto_register flag for ServerSideRender in the editor. * * Detects blocks that have the auto_register flag set in their supports * and passes them to JavaScript for auto-registration with ServerSideRender. From c1c194a25646c176b3f49f83a420dcef2252ffbc Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 17 Feb 2026 15:13:31 +0900 Subject: [PATCH 11/20] Remove default value from filter hook Co-authored-by: Weston Ruter --- src/wp-includes/block-supports/auto-register.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/block-supports/auto-register.php b/src/wp-includes/block-supports/auto-register.php index 5d655089efa2b..e2e7f9d5005fa 100644 --- a/src/wp-includes/block-supports/auto-register.php +++ b/src/wp-includes/block-supports/auto-register.php @@ -52,4 +52,4 @@ function wp_mark_auto_generate_control_attributes( array $args ): array { } // Priority 5 to mark original attributes before other filters (priority 10+) might add their own. -add_filter( 'register_block_type_args', 'wp_mark_auto_generate_control_attributes', 5, 1 ); +add_filter( 'register_block_type_args', 'wp_mark_auto_generate_control_attributes', 5 ); From ef9b5602961f0b69a2e4e4e37fcdc9bd94278df7 Mon Sep 17 00:00:00 2001 From: Aki Hamano Date: Tue, 17 Feb 2026 15:18:04 +0900 Subject: [PATCH 12/20] Relocate function and add underscore prefix --- src/wp-includes/blocks.php | 28 ++++++++++++++++++++++++++++ src/wp-includes/default-filters.php | 2 +- src/wp-includes/script-loader.php | 27 --------------------------- 3 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php index e7042b8266e54..2b992cbe94e91 100644 --- a/src/wp-includes/blocks.php +++ b/src/wp-includes/blocks.php @@ -3131,3 +3131,31 @@ function _wp_footnotes_force_filtered_html_on_import_filter( $arg ) { } return $arg; } + +/** + * Exposes blocks with auto_register flag for ServerSideRender in the editor. + * + * Detects blocks that have the auto_register flag set in their supports + * and passes them to JavaScript for auto-registration with ServerSideRender. + * + * @access private + * @since 7.0.0 + */ +function _wp_enqueue_auto_register_blocks() { + $auto_register_blocks = array(); + $registered_blocks = WP_Block_Type_Registry::get_instance()->get_all_registered(); + + foreach ( $registered_blocks as $block_name => $block_type ) { + if ( ! empty( $block_type->supports['auto_register'] ) && ! empty( $block_type->render_callback ) ) { + $auto_register_blocks[] = $block_name; + } + } + + if ( ! empty( $auto_register_blocks ) ) { + wp_add_inline_script( + 'wp-block-library', + sprintf( 'window.__unstableAutoRegisterBlocks = %s;', wp_json_encode( $auto_register_blocks ) ), + 'before' + ); + } +} diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php index 1a5732ac708ab..cc010a7b62202 100644 --- a/src/wp-includes/default-filters.php +++ b/src/wp-includes/default-filters.php @@ -623,7 +623,7 @@ add_action( 'enqueue_block_editor_assets', 'wp_enqueue_editor_format_library_assets' ); add_action( 'enqueue_block_editor_assets', 'wp_enqueue_block_editor_script_modules' ); add_action( 'enqueue_block_editor_assets', 'wp_enqueue_global_styles_css_custom_properties' ); -add_action( 'enqueue_block_editor_assets', 'wp_enqueue_auto_register_blocks' ); +add_action( 'enqueue_block_editor_assets', '_wp_enqueue_auto_register_blocks' ); add_action( 'wp_print_scripts', 'wp_just_in_time_script_localization' ); add_filter( 'print_scripts_array', 'wp_prototype_before_jquery' ); add_action( 'customize_controls_print_styles', 'wp_resource_hints', 1 ); diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index c80de2cb8f6bf..4384c7c10ed2a 100644 --- a/src/wp-includes/script-loader.php +++ b/src/wp-includes/script-loader.php @@ -4133,30 +4133,3 @@ function wp_html_custom_data_attribute_name( string $js_dataset_name ): ?string return $html_name; } - -/** - * Exposes blocks with auto_register flag for ServerSideRender in the editor. - * - * Detects blocks that have the auto_register flag set in their supports - * and passes them to JavaScript for auto-registration with ServerSideRender. - * - * @since 7.0.0 - */ -function wp_enqueue_auto_register_blocks() { - $auto_register_blocks = array(); - $registered_blocks = WP_Block_Type_Registry::get_instance()->get_all_registered(); - - foreach ( $registered_blocks as $block_name => $block_type ) { - if ( ! empty( $block_type->supports['auto_register'] ) && ! empty( $block_type->render_callback ) ) { - $auto_register_blocks[] = $block_name; - } - } - - if ( ! empty( $auto_register_blocks ) ) { - wp_add_inline_script( - 'wp-block-library', - sprintf( 'window.__unstableAutoRegisterBlocks = %s;', wp_json_encode( $auto_register_blocks ) ), - 'before' - ); - } -} From 506f76fe8d569938bdb9a9fa7d467cce887835c8 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 17 Feb 2026 15:45:04 +0900 Subject: [PATCH 13/20] Unit test: Add ticket number Co-authored-by: Weston Ruter --- tests/phpunit/tests/block-supports/auto-register.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/phpunit/tests/block-supports/auto-register.php b/tests/phpunit/tests/block-supports/auto-register.php index e3a2d9e2de2d2..c97edc6ef4b97 100644 --- a/tests/phpunit/tests/block-supports/auto-register.php +++ b/tests/phpunit/tests/block-supports/auto-register.php @@ -95,6 +95,8 @@ public function test_excludes_attributes_with_role_local() { /** * Tests that empty attributes are handled gracefully. + * + * @ticket 64639 */ public function test_handles_empty_attributes() { $settings = array( From bc9ada041a00a39f20218d969df669de1edcd916 Mon Sep 17 00:00:00 2001 From: Aki Hamano Date: Tue, 17 Feb 2026 15:50:39 +0900 Subject: [PATCH 14/20] Move require statement --- src/wp-settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-settings.php b/src/wp-settings.php index 3257d1014b752..0014dc692200d 100644 --- a/src/wp-settings.php +++ b/src/wp-settings.php @@ -394,6 +394,7 @@ require ABSPATH . WPINC . '/class-wp-block-supports.php'; require ABSPATH . WPINC . '/block-supports/utils.php'; require ABSPATH . WPINC . '/block-supports/align.php'; +require ABSPATH . WPINC . '/block-supports/auto-register.php'; require ABSPATH . WPINC . '/block-supports/custom-classname.php'; require ABSPATH . WPINC . '/block-supports/generated-classname.php'; require ABSPATH . WPINC . '/block-supports/settings.php'; @@ -410,7 +411,6 @@ require ABSPATH . WPINC . '/block-supports/background.php'; require ABSPATH . WPINC . '/block-supports/block-style-variations.php'; require ABSPATH . WPINC . '/block-supports/aria-label.php'; -require ABSPATH . WPINC . '/block-supports/auto-register.php'; require ABSPATH . WPINC . '/block-supports/anchor.php'; require ABSPATH . WPINC . '/block-supports/block-visibility.php'; require ABSPATH . WPINC . '/style-engine.php'; From c9d599dc014e0cf83fa159f0023b255c967fe886 Mon Sep 17 00:00:00 2001 From: Aki Hamano Date: Tue, 17 Feb 2026 15:55:19 +0900 Subject: [PATCH 15/20] Make support key camelCase --- src/wp-includes/block-supports/auto-register.php | 2 +- src/wp-includes/blocks.php | 6 +++--- tests/phpunit/tests/block-supports/auto-register.php | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/wp-includes/block-supports/auto-register.php b/src/wp-includes/block-supports/auto-register.php index e2e7f9d5005fa..66283bfc50605 100644 --- a/src/wp-includes/block-supports/auto-register.php +++ b/src/wp-includes/block-supports/auto-register.php @@ -31,7 +31,7 @@ function wp_mark_auto_generate_control_attributes( array $args ): array { return $args; } - $has_auto_register = ! empty( $args['supports']['auto_register'] ); + $has_auto_register = ! empty( $args['supports']['autoRegister'] ); if ( ! $has_auto_register ) { return $args; } diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php index 2b992cbe94e91..89007d0d0d036 100644 --- a/src/wp-includes/blocks.php +++ b/src/wp-includes/blocks.php @@ -3133,9 +3133,9 @@ function _wp_footnotes_force_filtered_html_on_import_filter( $arg ) { } /** - * Exposes blocks with auto_register flag for ServerSideRender in the editor. + * Exposes blocks with autoRegister flag for ServerSideRender in the editor. * - * Detects blocks that have the auto_register flag set in their supports + * Detects blocks that have the autoRegister flag set in their supports * and passes them to JavaScript for auto-registration with ServerSideRender. * * @access private @@ -3146,7 +3146,7 @@ function _wp_enqueue_auto_register_blocks() { $registered_blocks = WP_Block_Type_Registry::get_instance()->get_all_registered(); foreach ( $registered_blocks as $block_name => $block_type ) { - if ( ! empty( $block_type->supports['auto_register'] ) && ! empty( $block_type->render_callback ) ) { + if ( ! empty( $block_type->supports['autoRegister'] ) && ! empty( $block_type->render_callback ) ) { $auto_register_blocks[] = $block_name; } } diff --git a/tests/phpunit/tests/block-supports/auto-register.php b/tests/phpunit/tests/block-supports/auto-register.php index c97edc6ef4b97..edf63b75e2fa8 100644 --- a/tests/phpunit/tests/block-supports/auto-register.php +++ b/tests/phpunit/tests/block-supports/auto-register.php @@ -7,7 +7,7 @@ class Tests_Block_Supports_Auto_Register extends WP_UnitTestCase { /** - * Tests that attributes are marked when auto_register is enabled. + * Tests that attributes are marked when autoRegister is enabled. * * @ticket 64639 */ @@ -27,7 +27,7 @@ public function test_marks_attributes_with_auto_register_flag() { } /** - * Tests that attributes are not marked without auto_register flag. + * Tests that attributes are not marked without autoRegister flag. * * @ticket 64639 */ @@ -50,7 +50,7 @@ public function test_does_not_mark_attributes_without_auto_register() { */ public function test_excludes_attributes_with_source() { $settings = array( - 'supports' => array( 'auto_register' => true ), + 'supports' => array( 'autoRegister' => true ), 'attributes' => array( 'title' => array( 'type' => 'string' ), 'content' => array( @@ -77,7 +77,7 @@ public function test_excludes_attributes_with_source() { */ public function test_excludes_attributes_with_role_local() { $settings = array( - 'supports' => array( 'auto_register' => true ), + 'supports' => array( 'autoRegister' => true ), 'attributes' => array( 'title' => array( 'type' => 'string' ), 'blob' => array( @@ -100,7 +100,7 @@ public function test_excludes_attributes_with_role_local() { */ public function test_handles_empty_attributes() { $settings = array( - 'supports' => array( 'auto_register' => true ), + 'supports' => array( 'autoRegister' => true ), ); $result = wp_mark_auto_generate_control_attributes( $settings ); From c606521da36c2cd373cfcbdc5aa7730e179963ad Mon Sep 17 00:00:00 2001 From: Aki Hamano Date: Tue, 17 Feb 2026 16:46:39 +0900 Subject: [PATCH 16/20] Fix unit test --- tests/phpunit/tests/block-supports/auto-register.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/phpunit/tests/block-supports/auto-register.php b/tests/phpunit/tests/block-supports/auto-register.php index edf63b75e2fa8..661992e7d563e 100644 --- a/tests/phpunit/tests/block-supports/auto-register.php +++ b/tests/phpunit/tests/block-supports/auto-register.php @@ -13,7 +13,7 @@ class Tests_Block_Supports_Auto_Register extends WP_UnitTestCase { */ public function test_marks_attributes_with_auto_register_flag() { $settings = array( - 'supports' => array( 'auto_register' => true ), + 'supports' => array( 'autoRegister' => true ), 'attributes' => array( 'title' => array( 'type' => 'string' ), 'count' => array( 'type' => 'integer' ), From 658b7af6ed40562da9aabaaad86c4b66d1e75525 Mon Sep 17 00:00:00 2001 From: Aki Hamano Date: Tue, 17 Feb 2026 19:38:35 +0900 Subject: [PATCH 17/20] Add server-side type check --- .../block-supports/auto-register.php | 6 ++++ .../tests/block-supports/auto-register.php | 34 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/wp-includes/block-supports/auto-register.php b/src/wp-includes/block-supports/auto-register.php index 66283bfc50605..90d927d87caf0 100644 --- a/src/wp-includes/block-supports/auto-register.php +++ b/src/wp-includes/block-supports/auto-register.php @@ -18,6 +18,7 @@ * get auto-generated inspector controls. Attributes are excluded if they: * - Have a 'source' (HTML-derived, edited inline not via inspector) * - Have role 'local' (internal state, not user-configurable) + * - Have an unsupported type (only 'string', 'number', 'integer', 'boolean' are supported) * - Were added by block supports (added after this filter runs) * * @since 7.0.0 @@ -45,6 +46,11 @@ function wp_mark_auto_generate_control_attributes( array $args ): array { if ( isset( $attr_schema['role'] ) && 'local' === $attr_schema['role'] ) { continue; } + // Skip unsupported types (only 'string', 'number', 'integer', 'boolean' are supported). + $type = isset( $attr_schema['type'] ) ? $attr_schema['type'] : null; + if ( ! in_array( $type, array( 'string', 'number', 'integer', 'boolean' ), true ) ) { + continue; + } $args['attributes'][ $attr_key ]['autoGenerateControl'] = true; } diff --git a/tests/phpunit/tests/block-supports/auto-register.php b/tests/phpunit/tests/block-supports/auto-register.php index 661992e7d563e..552d4666fcd66 100644 --- a/tests/phpunit/tests/block-supports/auto-register.php +++ b/tests/phpunit/tests/block-supports/auto-register.php @@ -107,4 +107,38 @@ public function test_handles_empty_attributes() { $this->assertSame( $settings, $result ); } + + /** + * Tests that only allowed attributes are marked. + * + * @ticket 64639 + */ + public function test_excludes_unsupported_types() { + $settings = array( + 'supports' => array( 'autoRegister' => true ), + 'attributes' => array( + // Supported types + 'text' => array( 'type' => 'string' ), + 'price' => array( 'type' => 'number' ), + 'count' => array( 'type' => 'integer' ), + 'enabled' => array( 'type' => 'boolean' ), + // Unsupported types + 'metadata' => array( 'type' => 'object' ), + 'items' => array( 'type' => 'array' ), + 'config' => array( 'type' => 'null' ), + 'unknown' => array( 'type' => 'unknown' ), + ), + ); + + $result = wp_mark_auto_generate_control_attributes( $settings ); + + $this->assertTrue( $result['attributes']['text']['autoGenerateControl'] ); + $this->assertTrue( $result['attributes']['price']['autoGenerateControl'] ); + $this->assertTrue( $result['attributes']['count']['autoGenerateControl'] ); + $this->assertTrue( $result['attributes']['enabled']['autoGenerateControl'] ); + $this->assertArrayNotHasKey( 'autoGenerateControl', $result['attributes']['metadata'] ); + $this->assertArrayNotHasKey( 'autoGenerateControl', $result['attributes']['items'] ); + $this->assertArrayNotHasKey( 'autoGenerateControl', $result['attributes']['config'] ); + $this->assertArrayNotHasKey( 'autoGenerateControl', $result['attributes']['unknown'] ); + } } From b6348ef678be82eecdb1f2c5123eec10552b5b50 Mon Sep 17 00:00:00 2001 From: Aki Hamano Date: Tue, 17 Feb 2026 19:43:44 +0900 Subject: [PATCH 18/20] Fix PHP lint error --- tests/phpunit/tests/block-supports/auto-register.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/phpunit/tests/block-supports/auto-register.php b/tests/phpunit/tests/block-supports/auto-register.php index 552d4666fcd66..71754f247225b 100644 --- a/tests/phpunit/tests/block-supports/auto-register.php +++ b/tests/phpunit/tests/block-supports/auto-register.php @@ -118,10 +118,10 @@ public function test_excludes_unsupported_types() { 'supports' => array( 'autoRegister' => true ), 'attributes' => array( // Supported types - 'text' => array( 'type' => 'string' ), - 'price' => array( 'type' => 'number' ), - 'count' => array( 'type' => 'integer' ), - 'enabled' => array( 'type' => 'boolean' ), + 'text' => array( 'type' => 'string' ), + 'price' => array( 'type' => 'number' ), + 'count' => array( 'type' => 'integer' ), + 'enabled' => array( 'type' => 'boolean' ), // Unsupported types 'metadata' => array( 'type' => 'object' ), 'items' => array( 'type' => 'array' ), From e2b5ad44904d0dbeb60a04a4a6c19af91a8b8ed0 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 17 Feb 2026 20:22:13 +0900 Subject: [PATCH 19/20] Use null Coalescing Operator Co-authored-by: Miguel Fonseca <150562+mcsf@users.noreply.github.com> --- src/wp-includes/block-supports/auto-register.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/block-supports/auto-register.php b/src/wp-includes/block-supports/auto-register.php index 90d927d87caf0..774666614ec7e 100644 --- a/src/wp-includes/block-supports/auto-register.php +++ b/src/wp-includes/block-supports/auto-register.php @@ -47,7 +47,7 @@ function wp_mark_auto_generate_control_attributes( array $args ): array { continue; } // Skip unsupported types (only 'string', 'number', 'integer', 'boolean' are supported). - $type = isset( $attr_schema['type'] ) ? $attr_schema['type'] : null; + $type $attr_schema['type'] ?? null; if ( ! in_array( $type, array( 'string', 'number', 'integer', 'boolean' ), true ) ) { continue; } From 7f465c3ae3b1497cc02b7cb68a70cb72bdb9d84f Mon Sep 17 00:00:00 2001 From: Aki Hamano Date: Tue, 17 Feb 2026 20:36:54 +0900 Subject: [PATCH 20/20] Fix PHP fatal error --- src/wp-includes/block-supports/auto-register.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/block-supports/auto-register.php b/src/wp-includes/block-supports/auto-register.php index 774666614ec7e..83feedaaeeade 100644 --- a/src/wp-includes/block-supports/auto-register.php +++ b/src/wp-includes/block-supports/auto-register.php @@ -47,7 +47,7 @@ function wp_mark_auto_generate_control_attributes( array $args ): array { continue; } // Skip unsupported types (only 'string', 'number', 'integer', 'boolean' are supported). - $type $attr_schema['type'] ?? null; + $type = $attr_schema['type'] ?? null; if ( ! in_array( $type, array( 'string', 'number', 'integer', 'boolean' ), true ) ) { continue; }