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(
				'<div %1$s>%2$s: %3$d items</div>',
				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
This commit is contained in:
wildworks
2026-02-17 13:21:42 +00:00
parent 650e77076d
commit 7ffc2c4bd0
5 changed files with 92 additions and 1 deletions

View File

@@ -0,0 +1,61 @@
<?php
/**
* Auto-register block support.
*
* @package WordPress
* @since 7.0.0
*/
/**
* 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
* 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
* 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
* @access private
*
* @param array<string, mixed> $args Array of arguments for registering a block type.
* @return array<string, mixed> 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 );

View File

@@ -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'
);
}
}

View File

@@ -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 );

View File

@@ -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.

View File

@@ -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';