Skip to content

Commit

Permalink
Expanded block connections functionality
Browse files Browse the repository at this point in the history
The block connections concept received a major overhaul. Now, blocks can be connected to custom fields and future data sources. This works in a 3-step process:
- fetching connected block attributes
- collecting values from connected sources,
- and finally, updating the block's HTML with these values.

A new helper function called 'gutenberg_render_block_with_connection_value' is introduced which replaces either the whole HTML tag or a specific attribute with the connection value, based on the source and configuration parameters.

Also, adjusted the behavior in block-editor's custom fields when an attribute's value is empty. Instead of setting it as undefined, it is now set as an empty string, ensuring smoother handling.
  • Loading branch information
michalczaplinski committed Aug 9, 2023
1 parent 75ae849 commit 4b7e904
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 19 deletions.
79 changes: 62 additions & 17 deletions lib/experimental/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,23 @@ function gutenberg_register_metadata_attribute( $args ) {

$gutenberg_experiments = get_option( 'gutenberg-experiments' );
if ( $gutenberg_experiments && array_key_exists( 'gutenberg-connections', $gutenberg_experiments ) ) {

/**
* Renders the block meta attributes.
* Renders the block connections.
* Block connections allow to connect block attributes to custom fields or
* other data sources (in the future).
*
* Rendering block connections is a 3-step process:
* 1. Get the block attributes that have a connection. The connections are
* added in the editor and stored in the block attributes.
* 2. For each "connected" attribute, get the value from the connection
* source. For now, the only supported source is meta (custom fields).
* 3. Update the HTML of the block using the value from the connection. The
* HTML can be replaced in two ways:
* - If the attribute's "source" is `html`, replace the whole tag with the
* value from the connection.
* - If the attribute's "source" is `attribute`, replace the value of the
* corresponding HTML attribute with the value from the connection.
*
* @param string $block_content Block Content.
* @param array $block Block attributes.
Expand Down Expand Up @@ -191,22 +206,47 @@ function gutenberg_render_block_connections( $block_content, $block, $block_inst
}

// Get the content from the connection source.
$custom_value = $connection_sources[ $attribute_value['source'] ](
$connection_value = $connection_sources[ $attribute_value['source'] ](
$block_instance,
$attribute_value['value']
);

$tags = new WP_HTML_Tag_Processor( $block_content );
$found = $tags->next_tag(
array(
// TODO: In the future, when blocks other than Paragraph and Image are
// supported, we should build the full query from CSS selector.
'tag_name' => $block_type->attributes[ $attribute_name ]['selector'],
)
);
if ( ! $found ) {
return $block_content;
};
$attribute_config = $block_type->attributes[ $attribute_name ];

// Generate the new block content with the custom value.
$block_content = gutenberg_render_block_with_connection_value( $block_content, $connection_value, $attribute_config );

}

return $block_content;
}
add_filter( 'render_block', 'gutenberg_render_block_connections', 10, 3 );


/**
* Renders the block with the custom value from a connection source.
*
* @param string $block_content The HTML of the block originally passed to the `render_block` filter.
* @param mixed $custom_value The value obtained from the connection source (e.g. custom field).
* @param array $attribute_config The configuration of the connected
* attribute. It should contain the following keys:
* - selector: The HTML selector of the element that should be updated.
* - source: The source of the connection. Currently, only "html" and "attribute" are supported.
* - attribute: The name of the attribute that should be updated. Only used if the `source` is "attribute".
*/
function gutenberg_render_block_with_connection_value( $block_content, $custom_value, $attribute_config ) {
$tags = new WP_HTML_Tag_Processor( $block_content );
$block_selector_tag = $tags->next_tag(
array(
'tag_name' => $attribute_config['selector'],
)
);
if ( ! $block_selector_tag ) {
return $block_content;
}

// If the source is "html", it means that we should replace the whole tag with the meta value.
if ( 'html' === $attribute_config['source'] ) {
$tag_name = $tags->get_tag();
$markup = "<$tag_name>$custom_value</$tag_name>";
$updated_tags = new WP_HTML_Tag_Processor( $markup );
Expand All @@ -217,11 +257,16 @@ function gutenberg_render_block_connections( $block_content, $block, $block_inst
foreach ( $names as $name ) {
$updated_tags->set_attribute( $name, $tags->get_attribute( $name ) );
}

return $updated_tags->get_updated_html();
}

return $block_content;
// If the source is an attribute, it means that we should replace the attribute value with the custom value.
} elseif ( 'attribute' === $attribute_config['source'] ) {
$tags->set_attribute( $attribute_config['attribute'], $custom_value );
return $tags->get_updated_html();

} else {
// We don't support other sources yet.
return $block_content;
}
}
add_filter( 'render_block', 'gutenberg_render_block_connections', 10, 3 );
}
4 changes: 2 additions & 2 deletions packages/block-editor/src/hooks/custom-fields.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ const withInspectorControl = createHigherOrderComponent( ( BlockEdit ) => {
if ( nextValue === '' ) {
props.setAttributes( {
connections: undefined,
[ attributeName ]: undefined,
[ attributeName ]: '',
placeholder: undefined,
} );
} else {
Expand All @@ -105,7 +105,7 @@ const withInspectorControl = createHigherOrderComponent( ( BlockEdit ) => {
},
},
},
[ attributeName ]: undefined,
[ attributeName ]: '',
placeholder: sprintf(
'This content will be replaced on the frontend by the value of "%s" custom field.',
nextValue
Expand Down

0 comments on commit 4b7e904

Please sign in to comment.