From 7ffc2c4bd03746c69c773275fc9ffa5c158ce9c7 Mon Sep 17 00:00:00 2001 From: wildworks Date: Tue, 17 Feb 2026 13:21:42 +0000 Subject: [PATCH] Block Supports: Add autoRegister support for PHP-only block registration. Introduces block support for PHP-only block registration, enabling developers to register blocks in PHP without requiring JavaScript registration code. When a block declares `'supports' => array( 'autoRegister' => true )` along with a render callback, it is exposed to the client-side via a JavaScript global variable and registered automatically. Example usage: {{{ register_block_type( 'my-plugin/example', array( 'title' => 'My Example Block', 'attributes' => array( 'title' => array( 'type' => 'string', 'default' => 'Hello World', ), 'count' => array( 'type' => 'integer', 'default' => 5, ), ), 'render_callback' => function ( $attributes ) { return sprintf( '
%2$s: %3$d items
', get_block_wrapper_attributes(), esc_html( $attributes['title'] ), $attributes['count'] ); }, 'supports' => array( 'autoRegister' => true, ), ) ); }}} Props mcsf, oandregal, ramonopoly, westonruter, wildworks. Fixes #64639. Built from https://develop.svn.wordpress.org/trunk@61661 git-svn-id: http://core.svn.wordpress.org/trunk@60972 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/block-supports/auto-register.php | 61 ++++++++++++++++++++ wp-includes/blocks.php | 28 +++++++++ wp-includes/default-filters.php | 1 + wp-includes/version.php | 2 +- wp-settings.php | 1 + 5 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 wp-includes/block-supports/auto-register.php diff --git a/wp-includes/block-supports/auto-register.php b/wp-includes/block-supports/auto-register.php new file mode 100644 index 0000000000..83feedaaee --- /dev/null +++ b/wp-includes/block-supports/auto-register.php @@ -0,0 +1,61 @@ + $args Array of arguments for registering a block type. + * @return array Modified block type arguments. + */ +function wp_mark_auto_generate_control_attributes( array $args ): array { + if ( empty( $args['attributes'] ) || ! is_array( $args['attributes'] ) ) { + return $args; + } + + $has_auto_register = ! empty( $args['supports']['autoRegister'] ); + if ( ! $has_auto_register ) { + return $args; + } + + foreach ( $args['attributes'] as $attr_key => $attr_schema ) { + // Skip HTML-derived attributes (edited inline, not via inspector). + if ( ! empty( $attr_schema['source'] ) ) { + continue; + } + // Skip internal attributes (not user-configurable). + if ( isset( $attr_schema['role'] ) && 'local' === $attr_schema['role'] ) { + continue; + } + // Skip unsupported types (only 'string', 'number', 'integer', 'boolean' are supported). + $type = $attr_schema['type'] ?? null; + if ( ! in_array( $type, array( 'string', 'number', 'integer', 'boolean' ), true ) ) { + continue; + } + $args['attributes'][ $attr_key ]['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 ); diff --git a/wp-includes/blocks.php b/wp-includes/blocks.php index e7042b8266..89007d0d0d 100644 --- a/wp-includes/blocks.php +++ b/wp-includes/blocks.php @@ -3131,3 +3131,31 @@ function _wp_footnotes_force_filtered_html_on_import_filter( $arg ) { } return $arg; } + +/** + * Exposes blocks with autoRegister flag for ServerSideRender in the editor. + * + * Detects blocks that have the autoRegister 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['autoRegister'] ) && ! 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/wp-includes/default-filters.php b/wp-includes/default-filters.php index de0b374ef4..cc010a7b62 100644 --- a/wp-includes/default-filters.php +++ b/wp-includes/default-filters.php @@ -623,6 +623,7 @@ add_action( 'enqueue_block_editor_assets', 'wp_enqueue_editor_block_directory_as 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( '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/wp-includes/version.php b/wp-includes/version.php index 03ec6ee3d3..d32302e40c 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '7.0-alpha-61660'; +$wp_version = '7.0-alpha-61661'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema. diff --git a/wp-settings.php b/wp-settings.php index 60c220100f..0014dc6922 100644 --- a/wp-settings.php +++ b/wp-settings.php @@ -394,6 +394,7 @@ require ABSPATH . WPINC . '/block-patterns.php'; 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';