From 9ef1ee4793433f2e4d26bf92725b89d1abc9dd6d Mon Sep 17 00:00:00 2001 From: Matthew Reishus Date: Mon, 23 Sep 2024 17:47:54 -0500 Subject: [PATCH] new implementation --- src/wp-includes/blocks.php | 39 ++++++--- src/wp-includes/blocks/index.php | 17 ++++ .../class-wp-block-metadata-registry.php | 85 +++++++++++++++++++ src/wp-settings.php | 1 + 4 files changed, 129 insertions(+), 13 deletions(-) create mode 100644 src/wp-includes/class-wp-block-metadata-registry.php diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php index a53092e04e4d7..05b9253091ecc 100644 --- a/src/wp-includes/blocks.php +++ b/src/wp-includes/blocks.php @@ -375,6 +375,22 @@ function get_block_metadata_i18n_schema() { return $i18n_block_schema; } +/** + * Registers a block metadata collection. + * + * This function allows core and third-party plugins to register their block metadata + * collections in a centralized location. Registering collections can improve performance + * by avoiding multiple reads from the filesystem. + * + * @since 6.X.0 + * + * @param string $path The base path for the collection. + * @param string $manifest The path to the manifest file for the collection. + */ +function wp_register_block_metadata_collection( $path, $manifest ) { + WP_Block_Metadata_Registry::register_collection( $path, $manifest ); +} + /** * Registers a block type from the metadata stored in the `block.json` file. * @@ -402,29 +418,26 @@ function register_block_type_from_metadata( $file_or_folder, $args = array() ) { * instead of reading a JSON file per-block, and then decoding from JSON to PHP. * Using a static variable ensures that the metadata is only read once per request. */ - static $core_blocks_meta; - if ( ! $core_blocks_meta ) { - $core_blocks_meta = require ABSPATH . WPINC . '/blocks/blocks-json.php'; - } $metadata_file = ( ! str_ends_with( $file_or_folder, 'block.json' ) ) ? trailingslashit( $file_or_folder ) . 'block.json' : $file_or_folder; - $is_core_block = str_starts_with( $file_or_folder, ABSPATH . WPINC ); - // If the block is not a core block, the metadata file must exist. - $metadata_file_exists = $is_core_block || file_exists( $metadata_file ); + $metadata_dir = dirname( $metadata_file ); + $collection = dirname( $metadata_dir ); + $block_identifier = basename( $metadata_dir ); + + $has_metadata_from_registry = WP_Block_Metadata_Registry::has_metadata( $collection, $block_identifier ); + + // If the block is not registered in the metadata registry, the metadata file must exist. + $metadata_file_exists = $has_metadata_from_registry || file_exists( $metadata_file ); if ( ! $metadata_file_exists && empty( $args['name'] ) ) { return false; } // Try to get metadata from the static cache for core blocks. - $metadata = array(); - if ( $is_core_block ) { - $core_block_name = str_replace( ABSPATH . WPINC . '/blocks/', '', $file_or_folder ); - if ( ! empty( $core_blocks_meta[ $core_block_name ] ) ) { - $metadata = $core_blocks_meta[ $core_block_name ]; - } + if ( $has_metadata_from_registry ) { + $metadata = WP_Block_Metadata_Registry::get_metadata( $collection, $block_identifier ); } // If metadata is not found in the static cache, read it from the file. diff --git a/src/wp-includes/blocks/index.php b/src/wp-includes/blocks/index.php index 40967727da574..6582d07e9edf5 100644 --- a/src/wp-includes/blocks/index.php +++ b/src/wp-includes/blocks/index.php @@ -155,3 +155,20 @@ function register_core_block_types_from_metadata() { } } add_action( 'init', 'register_core_block_types_from_metadata' ); + +/** + * Registers the core block metadata collection. + * + * This function is hooked into the 'init' action with a priority of 9, + * ensuring that the core block metadata is registered before the regular + * block initialization that happens at priority 10. + * + * @since 6.X.0 + */ +function wp_register_core_block_metadata_collection() { + wp_register_block_metadata_collection( + BLOCKS_PATH, + BLOCKS_PATH . 'blocks-json.php' + ); +} +add_action( 'init', 'wp_register_core_block_metadata_collection', 9 ); diff --git a/src/wp-includes/class-wp-block-metadata-registry.php b/src/wp-includes/class-wp-block-metadata-registry.php new file mode 100644 index 0000000000000..f74b4774a7d8e --- /dev/null +++ b/src/wp-includes/class-wp-block-metadata-registry.php @@ -0,0 +1,85 @@ + $manifest, + 'metadata' => null, + ); + } + + /** + * Retrieves block metadata for a given block name within a specific collection. + * + * @since 6.X.0 + * + * @param string $path The base path of the collection. + * @param string $block_name The block name to look for. + * @return array|null The block metadata for the block, or null if not found. + */ + public static function get_metadata( $path, $block_name ) { + $path = rtrim( $path, '/' ); + if ( ! isset( self::$collections[ $path ] ) ) { + return null; + } + + $collection = &self::$collections[ $path ]; + + if ( null === $collection['metadata'] ) { + // Load the manifest file if not already loaded + $collection['metadata'] = require $collection['manifest']; + } + + return isset( $collection['metadata'][ $block_name ] ) ? $collection['metadata'][ $block_name ] : null; + } + + /** + * Checks if metadata exists for a given block name in a specific collection. + * + * @since 6.X.0 + * + * @param string $path The base path of the collection. + * @param string $block_name The block name to check for. + * @return bool True if metadata exists for the block, false otherwise. + */ + public static function has_metadata( $path, $block_name ) { + return null !== self::get_metadata( $path, $block_name ); + } + + /** + * Private constructor to prevent instantiation. + */ + private function __construct() { + // Prevent instantiation + } +} diff --git a/src/wp-settings.php b/src/wp-settings.php index 4643892ada0d6..e3bd5ca58dc54 100644 --- a/src/wp-settings.php +++ b/src/wp-settings.php @@ -354,6 +354,7 @@ require ABSPATH . WPINC . '/class-wp-block-type-registry.php'; require ABSPATH . WPINC . '/class-wp-block.php'; require ABSPATH . WPINC . '/class-wp-block-list.php'; +require ABSPATH . WPINC . '/class-wp-block-metadata-registry.php'; require ABSPATH . WPINC . '/class-wp-block-parser-block.php'; require ABSPATH . WPINC . '/class-wp-block-parser-frame.php'; require ABSPATH . WPINC . '/class-wp-block-parser.php';