Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
47 changes: 38 additions & 9 deletions src/wp-includes/class-wp-block.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,22 @@ class WP_Block {
*/
public $inner_content = array();

/**
* List of supported block attributes for block bindings.
*
* @since 6.9.0
* @var array
*
* @see WP_Block::process_block_bindings()
*/
private const BLOCK_BINDINGS_SUPPORTED_ATTRIBUTES = array(
'core/paragraph' => array( 'content' ),
'core/heading' => array( 'content' ),
'core/image' => array( 'id', 'url', 'title', 'alt' ),
'core/button' => array( 'url', 'text', 'linkTarget', 'rel' ),
'core/post-date' => array( 'datetime' ),
);

/**
* Constructor.
*
Expand Down Expand Up @@ -278,20 +294,33 @@ public function __get( $name ) {
* @return array The computed block attributes for the provided block bindings.
*/
private function process_block_bindings() {
$block_type = $this->name;
$parsed_block = $this->parsed_block;
$computed_attributes = array();
$supported_block_attributes = array(
'core/paragraph' => array( 'content' ),
'core/heading' => array( 'content' ),
'core/image' => array( 'id', 'url', 'title', 'alt' ),
'core/button' => array( 'url', 'text', 'linkTarget', 'rel' ),
'core/post-date' => array( 'datetime' ),

$supported_block_attributes =
self::BLOCK_BINDINGS_SUPPORTED_ATTRIBUTES[ $block_type ] ??
array();

/**
* Filters the supported block attributes for block bindings.
*
* The dynamic portion of the hook name, `$block_type`, refers to the block type
* whose attributes are being filtered.
*
* @since 6.9.0
*
* @param string[] $supported_block_attributes The block's attributes that are supported by block bindings.
*/
$supported_block_attributes = apply_filters(
"block_bindings_supported_attributes_{$block_type}",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can start with that and see if plugin authors raise the need to add a general filter, too.

$supported_block_attributes
);

// If the block doesn't have the bindings property, isn't one of the supported
// block types, or the bindings property is not an array, return the block content.
if (
! isset( $supported_block_attributes[ $this->name ] ) ||
empty( $supported_block_attributes ) ||
empty( $parsed_block['attrs']['metadata']['bindings'] ) ||
! is_array( $parsed_block['attrs']['metadata']['bindings'] )
) {
Expand All @@ -315,7 +344,7 @@ private function process_block_bindings() {
* Note that this also omits the `__default` attribute from the
* resulting array.
*/
foreach ( $supported_block_attributes[ $parsed_block['blockName'] ] as $attribute_name ) {
foreach ( $supported_block_attributes as $attribute_name ) {
// Retain any non-pattern override bindings that might be present.
$updated_bindings[ $attribute_name ] = isset( $bindings[ $attribute_name ] )
? $bindings[ $attribute_name ]
Expand All @@ -334,7 +363,7 @@ private function process_block_bindings() {

foreach ( $bindings as $attribute_name => $block_binding ) {
// If the attribute is not in the supported list, process next attribute.
if ( ! in_array( $attribute_name, $supported_block_attributes[ $this->name ], true ) ) {
if ( ! in_array( $attribute_name, $supported_block_attributes, true ) ) {
continue;
}
// If no source is provided, or that source is not registered, process next attribute.
Expand Down
77 changes: 77 additions & 0 deletions tests/phpunit/tests/block-bindings/render.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,27 @@ class WP_Block_Bindings_Render extends WP_UnitTestCase {
'label' => 'Test source',
);

/**
* Sets up shared fixtures.
*
* @since 6.9.0
*/
public static function wpSetUpBeforeClass() {
register_block_type(
'test/block',
array(
'attributes' => array(
'myAttribute' => array(
'type' => 'string',
),
),
'render_callback' => function ( $attributes ) {
return '<p>' . esc_html( $attributes['myAttribute'] ) . '</p>';
},
)
);
}

/**
* Tear down after each test.
*
Expand All @@ -31,6 +52,15 @@ public function tear_down() {
parent::tear_down();
}

/**
* Tear down after class.
*
* @since 6.9.0
*/
public static function wpTearDownAfterClass() {
unregister_block_type( 'test/block' );
}

/**
* Test if the block content is updated with the value returned by the source.
*
Expand Down Expand Up @@ -72,6 +102,53 @@ public function test_update_block_with_value_from_source() {
);
}

/**
* Test if the block_bindings_supported_attributes_{$block_type} filter is applied correctly.
*
* @ticket 62090
*/
public function test_filter_block_bindings_supported_attributes() {
$get_value_callback = function () {
return 'test source value';
};

register_block_bindings_source(
self::SOURCE_NAME,
array(
'label' => self::SOURCE_LABEL,
'get_value_callback' => $get_value_callback,
)
);

add_filter(
'block_bindings_supported_attributes_test/block',
function ( $supported_attributes ) {
$supported_attributes[] = 'myAttribute';
return $supported_attributes;
}
);

$block_content = <<<HTML
<!-- wp:test/block {"metadata":{"bindings":{"myAttribute":{"source":"test/source"}}}} -->
<p>This should not appear</p>
<!-- /wp:test/block -->
HTML;
$parsed_blocks = parse_blocks( $block_content );
$block = new WP_Block( $parsed_blocks[0] );
$result = $block->render();

$this->assertSame(
'test source value',
$block->attributes['myAttribute'],
"The 'myAttribute' attribute should be updated with the value returned by the source."
);
$this->assertSame(
'<p>test source value</p>',
trim( $result ),
'The block content should be updated with the value returned by the source.'
);
}

/**
* Test passing arguments to the source.
*
Expand Down
Loading