From 9ed6dc978a9c087fa0570939e9f4cf5205e5484e Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 15 Jan 2025 11:10:11 -0800 Subject: [PATCH] Implement a mechanism to register all block types from a block metadata collection. --- src/wp-includes/blocks.php | 26 ++++++++++++ .../class-wp-block-metadata-registry.php | 41 +++++++++++++++++++ .../tests/blocks/wpBlockMetadataRegistry.php | 32 +++++++++++++++ 3 files changed, 99 insertions(+) diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php index 25a4a7e3b29a1..192b512b69c1d 100644 --- a/src/wp-includes/blocks.php +++ b/src/wp-includes/blocks.php @@ -375,6 +375,32 @@ function get_block_metadata_i18n_schema() { return $i18n_block_schema; } +/** + * Registers all block types from a block metadata collection. + * + * This can either reference a previously registered metadata collection or, if the `$manifest` parameter is provided, + * register the metadata collection directly within the same function call. + * + * @since 6.8.0 + * @see wp_register_block_metadata_collection() + * @see register_block_type_from_metadata() + * + * @param string $path The absolute base path for the collection ( e.g., WP_PLUGIN_DIR . '/my-plugin/blocks/' ). + * @param string $manifest Optional. The absolute path to the manifest file containing the metadata collection, in + * order to register the collection. If this parameter is not provided, the `$path` parameter + * must reference a previously registered block metadata collection. + */ +function wp_register_block_types_from_metadata_collection( $path, $manifest = '' ) { + if ( $manifest ) { + wp_register_block_metadata_collection( $path, $manifest ); + } + + $block_metadata_files = WP_Block_Metadata_Registry::get_collection_block_metadata_files( $path ); + foreach ( $block_metadata_files as $block_metadata_file ) { + register_block_type_from_metadata( $block_metadata_file ); + } +} + /** * Registers a block metadata collection. * diff --git a/src/wp-includes/class-wp-block-metadata-registry.php b/src/wp-includes/class-wp-block-metadata-registry.php index 17bbf320d51b5..fd9712c028518 100644 --- a/src/wp-includes/class-wp-block-metadata-registry.php +++ b/src/wp-includes/class-wp-block-metadata-registry.php @@ -166,6 +166,47 @@ public static function get_metadata( $file_or_folder ) { return isset( $collection['metadata'][ $block_name ] ) ? $collection['metadata'][ $block_name ] : null; } + /** + * Gets the list of absolute paths to all block metadata files that are part of the given collection. + * + * For instance, if a block metadata collection is registered with path `WP_PLUGIN_DIR . '/my-plugin/blocks/'`, + * and the manifest file includes metadata for two blocks `'block-a'` and `'block-b'`, the result of this method + * will be an array containing: + * * `WP_PLUGIN_DIR . '/my-plugin/blocks/block-a/block.json'` + * * `WP_PLUGIN_DIR . '/my-plugin/blocks/block-b/block.json'` + * + * @since 6.8.0 + * + * @param string $path The absolute base path for a previously registered collection. + * @return string[] List of block metadata file paths, or an empty array if the given `$path` is invalid. + */ + public static function get_collection_block_metadata_files( $path ) { + $path = wp_normalize_path( rtrim( $path, '/' ) ); + + if ( ! isset( self::$collections[ $path ] ) ) { + _doing_it_wrong( + __METHOD__, + __( 'No registered block metadata collection was found for the provided path.' ), + '6.8.0' + ); + return array(); + } + + $collection = &self::$collections[ $path ]; + + if ( null === $collection['metadata'] ) { + // Load the manifest file if not already loaded + $collection['metadata'] = require $collection['manifest']; + } + + return array_map( + static function ( $block_name ) use ( $path ) { + return "{$path}/{$block_name}/block.json"; + }, + array_keys( $collection['metadata'] ) + ); + } + /** * Finds the collection path for a given file or folder. * diff --git a/tests/phpunit/tests/blocks/wpBlockMetadataRegistry.php b/tests/phpunit/tests/blocks/wpBlockMetadataRegistry.php index 3f0ec006b0a0a..630b7bd2a4b03 100644 --- a/tests/phpunit/tests/blocks/wpBlockMetadataRegistry.php +++ b/tests/phpunit/tests/blocks/wpBlockMetadataRegistry.php @@ -4,6 +4,7 @@ * Tests for WP_Block_Metadata_Registry class. * * @group blocks + * @coversDefaultClass WP_Block_Metadata_Registry */ class Tests_Blocks_WpBlockMetadataRegistry extends WP_UnitTestCase { @@ -88,4 +89,35 @@ public function test_register_collection_with_non_existent_path() { $result = WP_Block_Metadata_Registry::register_collection( $non_existent_path, $this->temp_manifest_file ); $this->assertFalse( $result, 'Non-existent path should not be registered' ); } + + /** + * Tests that the `get_collection_block_metadata_files()` method returns the expected list of block metadata files. + * + * @ticket 62267 + * @covers ::get_collection_block_metadata_files + */ + public function test_get_collection_block_metadata_files() { + $path = WP_PLUGIN_DIR . '/test-plugin/data/block-types'; + $manifest_data = array( + 'a-block' => array( + 'name' => 'a-block', + 'title' => 'A Block', + ), + 'another-block' => array( + 'name' => 'another-block', + 'title' => 'Another Block', + ), + ); + + file_put_contents( $this->temp_manifest_file, 'assertTrue( WP_Block_Metadata_Registry::register_collection( $path, $this->temp_manifest_file ) ); + $this->assertSame( + array( + WP_PLUGIN_DIR . '/test-plugin/data/block-types/a-block/block.json', + WP_PLUGIN_DIR . '/test-plugin/data/block-types/another-block/block.json', + ), + WP_Block_Metadata_Registry::get_collection_block_metadata_files( $path ) + ); + } }