Skip to content

Commit

Permalink
new implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
mreishus committed Sep 24, 2024
1 parent 78b547e commit 6e4b453
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 13 deletions.
39 changes: 26 additions & 13 deletions src/wp-includes/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -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.
Expand Down
17 changes: 17 additions & 0 deletions src/wp-includes/blocks/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
85 changes: 85 additions & 0 deletions src/wp-includes/class-wp-block-metadata-registry.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php
/**
* Block Metadata Registry
*
* @package WordPress
* @subpackage Blocks
* @since 6.X.0
*/

/**
* Class used for managing block metadata collections.
*
* @since 6.X.0
*/
class WP_Block_Metadata_Registry {

/**
* Container for storing block metadata collections.
*
* @since 6.X.0
* @var array
*/
private static $collections = array();

/**
* Registers a block metadata collection.
*
* @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.
*/
public static function register_collection( $path, $manifest ) {
$path = rtrim( $path, '/' );
self::$collections[ $path ] = array(
'manifest' => $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
}
}