diff --git a/lib/compat/wordpress-6.5/blocks.php b/lib/compat/wordpress-6.5/blocks.php index c3304a8f4a07f..4d5040878e210 100644 --- a/lib/compat/wordpress-6.5/blocks.php +++ b/lib/compat/wordpress-6.5/blocks.php @@ -158,13 +158,43 @@ function gutenberg_block_bindings_replace_html( $block_content, $block_name, str } /** - * Process the block bindings attribute. + * Check if the parsed block is supported by block bindings and it includes the bindings attribute. * - * @param string $block_content Block Content. * @param array $parsed_block The full block, including name and attributes. - * @param WP_Block $block_instance The block instance. */ -function gutenberg_process_block_bindings( $block_content, $parsed_block, $block_instance ) { +function gutenberg_is_valid_block_for_block_bindings( $parsed_block ) { + $supported_blocks = array( + 'core/paragraph', + 'core/heading', + 'core/image', + 'core/button', + ); + + // Check if the block is supported. + if ( + ! in_array( $parsed_block['blockName'], $supported_blocks, true ) || + empty( $parsed_block['attrs']['metadata']['bindings'] ) || + ! is_array( $parsed_block['attrs']['metadata']['bindings'] ) + ) { + return false; + } + + return true; +} + +/** + * Check if the binding created is valid. + * + * @param array $parsed_block The full block, including name and attributes. + * @param string $attribute_name The attribute name being processed. + * @param array $block_binding The block binding configuration. + */ +function gutenberg_is_valid_block_binding( $parsed_block, $attribute_name, $block_binding ) { + // Check if it is a valid block. + if ( ! gutenberg_is_valid_block_for_block_bindings( $parsed_block ) ) { + return false; + } + $supported_block_attrs = array( 'core/paragraph' => array( 'content' ), 'core/heading' => array( 'content' ), @@ -172,59 +202,82 @@ function gutenberg_process_block_bindings( $block_content, $parsed_block, $block 'core/button' => array( 'url', 'text', 'linkTarget', 'rel' ), ); - // If the block doesn't have the bindings property or isn't one of the supported block types, return. - if ( - ! isset( $supported_block_attrs[ $block_instance->name ] ) || - empty( $parsed_block['attrs']['metadata']['bindings'] ) || - ! is_array( $parsed_block['attrs']['metadata']['bindings'] ) - ) { - return $block_content; + // Check if the attribute is not in the supported list. + if ( ! in_array( $attribute_name, $supported_block_attrs[ $parsed_block['blockName'] ], true ) ) { + return false; + } + // Check if no source is provided, or that source is not registered. + if ( ! isset( $block_binding['source'] ) || ! is_string( $block_binding['source'] ) || null === get_block_bindings_source( $block_binding['source'] ) ) { + return false; } - /* - * Assuming the following format for the bindings property of the "metadata" attribute: - * - * "bindings": { - * "title": { - * "source": "core/post-meta", - * "args": { "key": "text_custom_field" } - * }, - * "url": { - * "source": "core/post-meta", - * "args": { "key": "url_custom_field" } - * } - * } - */ + return true; +} - $modified_block_content = $block_content; - foreach ( $parsed_block['attrs']['metadata']['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_attrs[ $block_instance->name ], true ) ) { - continue; - } - // If no source is provided, or that source is not registered, process next attribute. - if ( ! isset( $block_binding['source'] ) || ! is_string( $block_binding['source'] ) ) { - continue; +/** + * Replace the block attributes and the HTML with the values from block bindings. + * These filters are temporary for backward-compatibility. It is handled properly without filters in core. + * + */ +add_filter( + 'render_block_data', + /** + * Filter to modify the block attributes with a placeholder value for each attribute that has a block binding. + * + * @param array $parsed_block The full block, including name and attributes. + */ + function ( $parsed_block ) { + if ( ! gutenberg_is_valid_block_for_block_bindings( $parsed_block ) ) { + return $parsed_block; } - $block_binding_source = get_block_bindings_source( $block_binding['source'] ); - if ( null === $block_binding_source ) { - continue; + foreach ( $parsed_block['attrs']['metadata']['bindings'] as $attribute_name => $block_binding ) { + if ( ! gutenberg_is_valid_block_binding( $parsed_block, $attribute_name, $block_binding ) ) { + continue; + } + // Adds a placeholder value that will get replaced by the replace_html in the render_block filter. + $parsed_block['attrs'][ $attribute_name ] = 'placeholder'; } + return $parsed_block; + }, + 20, + 1 +); + +add_filter( + 'render_block', + /** + * Filter to replace the placeholder value with the actual value from the block binding. + * + * @param string $block_content Block Content. + * @param array $parsed_block The full block, including name and attributes. + * @param WP_Block $block_instance The block instance. + */ + function ( $block_content, $parsed_block, $block_instance ) { + if ( ! gutenberg_is_valid_block_for_block_bindings( $parsed_block ) ) { + return $block_content; + } + $modified_block_content = $block_content; + foreach ( $parsed_block['attrs']['metadata']['bindings'] as $attribute_name => $block_binding ) { + if ( ! gutenberg_is_valid_block_binding( $parsed_block, $attribute_name, $block_binding ) ) { + continue; + } - $source_args = ! empty( $block_binding['args'] ) && is_array( $block_binding['args'] ) ? $block_binding['args'] : array(); - $source_value = $block_binding_source->get_value( $source_args, $block_instance, $attribute_name ); + $block_binding_source = get_block_bindings_source( $block_binding['source'] ); + $source_args = ! empty( $block_binding['args'] ) && is_array( $block_binding['args'] ) ? $block_binding['args'] : array(); + $source_value = $block_binding_source->get_value( $source_args, $block_instance, $attribute_name ); - // If the value is not null, process the HTML based on the block and the attribute. - if ( ! is_null( $source_value ) ) { - $modified_block_content = gutenberg_block_bindings_replace_html( $modified_block_content, $block_instance->name, $attribute_name, $source_value ); + // If the value is not null, process the HTML based on the block and the attribute. + if ( ! is_null( $source_value ) ) { + $modified_block_content = gutenberg_block_bindings_replace_html( $modified_block_content, $block_instance->name, $attribute_name, $source_value ); + } } - } - - return $modified_block_content; -} -add_filter( 'render_block', 'gutenberg_process_block_bindings', 20, 3 ); + return $modified_block_content; + }, + 20, + 3 +); /** * Enable the viewStyle block API for core versions < 6.5