Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix block registration from metadata #3501

Closed
wants to merge 45 commits into from
Closed
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
2a31ff4
pass $args earlier
aristath Oct 20, 2022
7daab55
Add empty string as default value for $file_or_folder
aristath Oct 20, 2022
51f6083
$metadata is an array
aristath Oct 20, 2022
ef39e83
fix for translations conditions
aristath Oct 20, 2022
392b8ae
Return false if name is not defined
aristath Oct 20, 2022
b236265
removed default value
aristath Oct 20, 2022
92ac48a
simplify condition
aristath Oct 20, 2022
c5edb5b
fix for core blocks caches
aristath Oct 20, 2022
b5ecea7
move render_callback calculations before parsing the $args
aristath Oct 20, 2022
000ef58
more WIP
aristath Oct 20, 2022
35e526e
more render callback a bit earlier
aristath Oct 20, 2022
14cad2c
tweak the check
aristath Oct 20, 2022
6d426b5
minor tweak
aristath Oct 20, 2022
d2f4977
Add PHPUnit tests & fix discovered bug
aristath Mar 2, 2023
39c2c0d
Update src/wp-includes/blocks.php
aristath Mar 2, 2023
536666e
docs fix (copy/paste error)
aristath Mar 2, 2023
9400e13
Merge remote-tracking branch 'aristath/fix/block-registration' into f…
aristath Mar 2, 2023
45d3229
Update tests/phpunit/tests/blocks/register.php
aristath Mar 2, 2023
910df65
Update tests/phpunit/tests/blocks/register.php
aristath Mar 2, 2023
fe37d14
copy/paste
aristath Mar 2, 2023
b0913e1
wording improvement
aristath Mar 2, 2023
7df228e
Add messages to tests
aristath Mar 2, 2023
927a6a4
typo fix
aristath Mar 3, 2023
8e3a1e7
Merge branch 'trunk' into fix/block-registration
aristath Jul 4, 2023
d5dfea3
fix failing test from merge conflict
aristath Jul 4, 2023
a45eac6
Merge branch 'trunk' into fix/block-registration
aristath Jul 5, 2023
d1d47bc
Add more tests
aristath Jul 6, 2023
eccbf70
Merge branch 'trunk' into fix/block-registration
aristath Jul 6, 2023
fd2f493
Merge branch 'trunk' into fix/block-registration
aristath Jul 10, 2023
614a522
Update tests/phpunit/tests/blocks/register.php
aristath Jul 10, 2023
0ffe03a
Merge remote-tracking branch 'aristath/fix/block-registration' into f…
aristath Jul 10, 2023
69c8372
Update tests/phpunit/tests/blocks/register.php
aristath Jul 10, 2023
75e814b
Merge remote-tracking branch 'aristath/fix/block-registration' into f…
aristath Jul 10, 2023
3b5fb15
Move dataProvider function
aristath Jul 10, 2023
4a6136b
Update tests/phpunit/tests/blocks/register.php
aristath Jul 10, 2023
9174edd
Merge branch 'trunk' into fix/block-registration
aristath Jul 11, 2023
2c32ffa
Merge branch 'trunk' into fix/block-registration
aristath Jul 18, 2023
47586a9
Don't check if file exists for core blocks
aristath Jul 18, 2023
280992d
resolve rebase conflicts
aristath Jul 19, 2023
a898362
Update src/wp-includes/blocks.php
aristath Jul 19, 2023
551f3f4
Merge branch 'trunk' into fix/block-registration
aristath Jul 19, 2023
6ab5c1f
Merge branch 'trunk' into fix/block-registration
aristath Jul 25, 2023
50f0346
Merge branch 'trunk' into fix/block-registration
aristath Sep 13, 2023
3f96fd8
Merge branch 'trunk' into fix/block-registration
spacedmonkey Sep 26, 2023
f2feb9f
Merge branch 'trunk' into fix/block-registration
aristath Oct 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 46 additions & 42 deletions src/wp-includes/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -368,13 +368,14 @@ function register_block_type_from_metadata( $file_or_folder, $args = array() ) {
$file_or_folder;

$is_core_block = str_starts_with( $file_or_folder, ABSPATH . WPINC );

if ( ! $is_core_block && ! file_exists( $metadata_file ) ) {
// If the block is not a core block, the metadata file must exist.
$metadata_file_exists = $is_core_block || 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 = false;
$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 ] ) ) {
Expand All @@ -383,14 +384,14 @@ function register_block_type_from_metadata( $file_or_folder, $args = array() ) {
}

// If metadata is not found in the static cache, read it from the file.
if ( ! $metadata ) {
if ( $metadata_file_exists && empty( $metadata ) ) {
$metadata = wp_json_file_decode( $metadata_file, array( 'associative' => true ) );
}

if ( ! is_array( $metadata ) || empty( $metadata['name'] ) ) {
if ( ! is_array( $metadata ) || ( empty( $metadata['name'] ) && empty( $args['name'] ) ) ) {
aristath marked this conversation as resolved.
Show resolved Hide resolved
return false;
}
$metadata['file'] = wp_normalize_path( realpath( $metadata_file ) );
$metadata['file'] = $metadata_file_exists ? wp_normalize_path( realpath( $metadata_file ) ) : null;
spacedmonkey marked this conversation as resolved.
Show resolved Hide resolved

/**
* Filters the metadata provided for registering a block type.
Expand Down Expand Up @@ -420,6 +421,7 @@ function register_block_type_from_metadata( $file_or_folder, $args = array() ) {
$settings = array();
$property_mappings = array(
'apiVersion' => 'api_version',
'name' => 'name',
'title' => 'title',
'category' => 'category',
'parent' => 'parent',
Expand All @@ -442,18 +444,50 @@ function register_block_type_from_metadata( $file_or_folder, $args = array() ) {
foreach ( $property_mappings as $key => $mapped_key ) {
if ( isset( $metadata[ $key ] ) ) {
$settings[ $mapped_key ] = $metadata[ $key ];
if ( $textdomain && isset( $i18n_schema->$key ) ) {
if ( $metadata_file_exists && $textdomain && isset( $i18n_schema->$key ) ) {
aristath marked this conversation as resolved.
Show resolved Hide resolved
aristath marked this conversation as resolved.
Show resolved Hide resolved
$settings[ $mapped_key ] = translate_settings_using_i18n_schema( $i18n_schema->$key, $settings[ $key ], $textdomain );
}
}
}

if ( ! empty( $metadata['render'] ) ) {
$template_path = wp_normalize_path(
realpath(
dirname( $metadata['file'] ) . '/' .
remove_block_asset_path_prefix( $metadata['render'] )
)
);
if ( $template_path ) {
/**
* Renders the block on the server.
*
* @since 6.1.0
*
* @param array $attributes Block attributes.
* @param string $content Block default content.
* @param WP_Block $block Block instance.
*
* @return string Returns the block content.
aristath marked this conversation as resolved.
Show resolved Hide resolved
*/
$settings['render_callback'] = static function ( $attributes, $content, $block ) use ( $template_path ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
ob_start();
require $template_path;
return ob_get_clean();
};
}
}

$settings = array_merge( $settings, $args );

$script_fields = array(
'editorScript' => 'editor_script_handles',
'script' => 'script_handles',
'viewScript' => 'view_script_handles',
);
foreach ( $script_fields as $metadata_field_name => $settings_field_name ) {
if ( ! empty( $settings[ $metadata_field_name ] ) ) {
$metadata[ $metadata_field_name ] = $settings[ $metadata_field_name ];
}
aristath marked this conversation as resolved.
Show resolved Hide resolved
if ( ! empty( $metadata[ $metadata_field_name ] ) ) {
$scripts = $metadata[ $metadata_field_name ];
$processed_scripts = array();
Expand Down Expand Up @@ -486,6 +520,9 @@ function register_block_type_from_metadata( $file_or_folder, $args = array() ) {
'style' => 'style_handles',
);
foreach ( $style_fields as $metadata_field_name => $settings_field_name ) {
if ( ! empty( $settings[ $metadata_field_name ] ) ) {
$metadata[ $metadata_field_name ] = $settings[ $metadata_field_name ];
}
if ( ! empty( $metadata[ $metadata_field_name ] ) ) {
$styles = $metadata[ $metadata_field_name ];
$processed_styles = array();
Expand Down Expand Up @@ -513,33 +550,6 @@ function register_block_type_from_metadata( $file_or_folder, $args = array() ) {
}
}

if ( ! empty( $metadata['render'] ) ) {
$template_path = wp_normalize_path(
realpath(
dirname( $metadata['file'] ) . '/' .
remove_block_asset_path_prefix( $metadata['render'] )
)
);
if ( $template_path ) {
/**
* Renders the block on the server.
*
* @since 6.1.0
*
* @param array $attributes Block attributes.
* @param string $content Block default content.
* @param WP_Block $block Block instance.
*
* @return string Returns the block content.
*/
$settings['render_callback'] = static function ( $attributes, $content, $block ) use ( $template_path ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
ob_start();
require $template_path;
return ob_get_clean();
};
}
}

/**
* Filters the settings determined from the block type metadata.
*
Expand All @@ -548,15 +558,9 @@ function register_block_type_from_metadata( $file_or_folder, $args = array() ) {
* @param array $settings Array of determined settings for registering a block type.
* @param array $metadata Metadata provided for registering a block type.
*/
$settings = apply_filters(
'block_type_metadata_settings',
array_merge(
$settings,
$args
),
$metadata
);
$settings = apply_filters( 'block_type_metadata_settings', $settings, $metadata );
aristath marked this conversation as resolved.
Show resolved Hide resolved

$metadata['name'] = ! empty( $settings['name'] ) ? $settings['name'] : $metadata['name'];
return WP_Block_Type_Registry::get_instance()->register(
$metadata['name'],
$settings
Expand Down
120 changes: 120 additions & 0 deletions tests/phpunit/tests/blocks/register.php
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,126 @@ public function test_metadata_not_found_in_the_current_directory() {
$this->assertFalse( $result );
}

/**
* Tests registering a block using arguments instead of a block.json file.
*
* @ticket 56865
*
* @covers ::register_block_type_from_metadata
*/
public function test_register_block_type_from_metadata_with_arguments() {
$result = register_block_type_from_metadata(
'',
array(
'api_version' => 2,
'name' => 'tests/notice-from-array',
'title' => 'Notice from array',
'category' => 'common',
'icon' => 'star',
'description' => 'Shows warning, error or success notices… (registered from an array)',
'keywords' => array(
'alert',
'message',
),
'textdomain' => 'notice-from-array',
)
);

$this->assertInstanceOf( 'WP_Block_Type', $result, 'The block was not registered' );
$this->assertSame( 2, $result->api_version, 'The API version is incorrect' );
$this->assertSame( 'tests/notice-from-array', $result->name, 'The block name is incorrect' );
$this->assertSame( 'Notice from array', $result->title, 'The block title is incorrect' );
$this->assertSame( 'common', $result->category, 'The block category is incorrect' );
$this->assertSame( 'star', $result->icon, 'The block icon is incorrect' );
$this->assertSame(
'Shows warning, error or success notices… (registered from an array)',
$result->description,
'The block description is incorrect'
);
$this->assertSameSets( array( 'alert', 'message' ), $result->keywords, 'The block keywords are incorrect' );
}

/**
* Tests that defined $args can properly override the block.json file.
*
* @ticket 56865
aristath marked this conversation as resolved.
Show resolved Hide resolved
*
* @covers ::register_block_type_from_metadata
*/
public function test_block_registers_with_args_override() {
$result = register_block_type_from_metadata(
DIR_TESTDATA . '/blocks/notice',
array(
'name' => 'tests/notice-with-overrides',
'title' => 'Overriden title',
aristath marked this conversation as resolved.
Show resolved Hide resolved
'style' => array( 'tests-notice-style-overridden' ),
)
);

$this->assertInstanceOf( 'WP_Block_Type', $result, 'The block was not registered' );
$this->assertSame( 2, $result->api_version, 'The API version is incorrect' );
$this->assertSame( 'tests/notice-with-overrides', $result->name, 'The block name was not overridden' );
$this->assertSame( 'Overriden title', $result->title, 'The block title was not overridden' );
$this->assertSameSets(
array( 'tests-notice-editor-script' ),
$result->editor_script_handles,
'The block editor script is incorrect'
);
$this->assertSameSets(
array( 'tests-notice-style-overridden' ),
$result->style_handles,
'The block style was not overridden'
);
$this->assertIsCallable( $result->render_callback );
}

aristath marked this conversation as resolved.
Show resolved Hide resolved
/**
* Tests that when the `name` is missing, `register_block_type_from_metadata`
* will return `false`.
*
* @ticket 56865
*
* @covers ::register_block_type_from_metadata
*
* @dataProvider data_register_block_registers_with_args_override_returns_false_when_name_is_missing
*
* @param string $file The metadata file.
* @param array $args Array of block type arguments.
*/
public function test_block_registers_with_args_override_returns_false_when_name_is_missing( $file, $args ) {
$this->assertFalse( register_block_type_from_metadata( $file, $args ) );
}

/**
* Data provider.
*
* @return array[]
*/
public function data_register_block_registers_with_args_override_returns_false_when_name_is_missing() {
aristath marked this conversation as resolved.
Show resolved Hide resolved
return array(
'no block.json file and no name argument' => array(
'file' => '', // No block.json file.
'args' => array(
'title' => 'Overriden title',
'style' => array( 'tests-notice-style-overridden' ),
),
),
'existing file and args not an array' => array(
// A file that exists but is empty. This will bypass the file_exists() check.
'file' => DIR_TESTDATA . '/blocks/notice/block.js',
'args' => false,
),
'existing file and args[name] missing' => array(
// A file that exists but is empty. This will bypass the file_exists() check.
'file' => DIR_TESTDATA . '/blocks/notice/block.js',
'args' => array(
'title' => 'Overriden title',
'style' => array( 'tests-notice-style-overridden' ),
),
),
);
}

/**
* Tests that the function returns the registered block when the `block.json`
* is found in the fixtures directory.
Expand Down
Loading