-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Add block bindings API basis and metadata source #56867
Changes from 20 commits
4100933
edee28a
01189c7
5e38246
35d03dd
a19009c
87e333d
081ed5c
ecd1377
7543606
1017d4d
8096402
5d5c68c
24ff0d2
6c7fe63
6176f15
feaf22d
4689e76
f6bc2c0
3590330
5b5546f
01d834b
d215035
159cb0a
1178ba8
006872f
cc59e1b
4f651c2
7dd4368
62a8bc1
b95ac5e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
<?php | ||
/** | ||
* Define the mechanism to replpace the HTML depending on the block attributes. | ||
* | ||
* @package gutenberg | ||
*/ | ||
|
||
if ( ! function_exists( 'block_bindings_replace_html' ) ) { | ||
/** | ||
* Depending on the block attributes, replace the proper HTML based on the value returned by the source. | ||
* | ||
* @param string $block_content Block Content. | ||
* @param string $block_name The name of the block to process. | ||
* @param string $block_attr The attribute of the block we want to process. | ||
* @param string $source_value The value used to replace the HTML. | ||
*/ | ||
function block_bindings_replace_html( $block_content, $block_name, $block_attr, $source_value ) { | ||
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block_name ); | ||
if ( null === $block_type ) { | ||
return; | ||
} | ||
|
||
// Depending on the attribute source, the processing will be different. | ||
// TODO: Get the type from the block attribute definition and modify/validate the value returned by the source if needed. | ||
switch ( $block_type->attributes[ $block_attr ]['source'] ) { | ||
case 'html': | ||
$p = new WP_HTML_Tag_Processor( $block_content ); | ||
if ( ! $p->next_tag( | ||
array( | ||
// TODO: build the query from CSS selector. | ||
'tag_name' => $block_type->attributes[ $block_attr ]['selector'], | ||
) | ||
) ) { | ||
return $block_content; | ||
} | ||
// TODO: We should use a `set_inner_html` method once available. | ||
$tag_name = $p->get_tag(); | ||
$markup = "<$tag_name>" . esc_html( $source_value ) . "</$tag_name>"; | ||
$p2 = new WP_HTML_Tag_Processor( $markup ); | ||
$p2->next_tag(); | ||
$names = $p->get_attribute_names_with_prefix( '' ); | ||
foreach ( $names as $name ) { | ||
$p2->set_attribute( $name, $p->get_attribute( $name ) ); | ||
} | ||
return $p2->get_updated_html(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mentioned in #56704 (comment) that this unfortunately disregards any markup before or after the found tag, so it won't work for button which is a I realize we need There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're totally right. I just made a commit that tries to make it work with heading and button structures: link. Whenever the Let me know if that works for you 🙂 |
||
break; | ||
|
||
case 'attribute': | ||
$p = new WP_HTML_Tag_Processor( $block_content ); | ||
if ( ! $p->next_tag( | ||
array( | ||
// TODO: build the query from CSS selector. | ||
'tag_name' => $block_type->attributes[ $block_attr ]['selector'], | ||
) | ||
) ) { | ||
return $block_content; | ||
} | ||
$p->set_attribute( $block_type->attributes[ $block_attr ]['attribute'], esc_attr( $source_value ) ); | ||
return $p->get_updated_html(); | ||
break; | ||
|
||
default: | ||
return $block_content; | ||
break; | ||
} | ||
return; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
/** | ||
* Require the necessary files. | ||
* | ||
* @package gutenberg | ||
*/ | ||
|
||
require_once __DIR__ . '/sources/index.php'; | ||
require_once __DIR__ . '/html-processing.php'; | ||
|
||
// Register the sources. | ||
$gutenberg_experiments = get_option( 'gutenberg-experiments' ); | ||
if ( $gutenberg_experiments ) { | ||
if ( array_key_exists( 'gutenberg-pattern-partial-syncing', $gutenberg_experiments ) ) { | ||
require_once __DIR__ . '/sources/pattern.php'; | ||
} | ||
if ( array_key_exists( 'gutenberg-connections', $gutenberg_experiments ) ) { | ||
require_once __DIR__ . '/sources/metadata.php'; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?php | ||
/** | ||
* Define the mechanism to add new sources available in the block bindings API. | ||
* | ||
* @package gutenberg | ||
*/ | ||
|
||
global $block_bindings_sources; | ||
$block_bindings_sources = array(); | ||
if ( ! function_exists( 'register_block_bindings_source' ) ) { | ||
/** | ||
* Function to register a new source. | ||
* | ||
* @param string $source_name The name of the source. | ||
* @param function $source_callback The callback executed when the source is processed in the server. | ||
*/ | ||
function register_block_bindings_source( $source_name, $source_callback ) { | ||
// We might want to add some validation here, for the name and for the apply_source callback. | ||
// To ensure the register sources are valid. | ||
global $block_bindings_sources; | ||
$block_bindings_sources[ $source_name ] = array( 'apply_source' => $source_callback ); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<?php | ||
/** | ||
* Add the metadata source to the block bindings API. | ||
* | ||
* @package gutenberg | ||
*/ | ||
|
||
if ( function_exists( 'register_block_bindings_source' ) ) { | ||
$metadata_source_callback = function ( $source_attrs, $block_content, $block, $block_instance ) { | ||
// Use the postId attribute if available, otherwise use the context. | ||
if ( isset( $source_attrs['postId'] ) ) { | ||
$post_id = $source_attrs['postId']; | ||
} else { | ||
// I tried using $block_instance->context['postId'] but it wasn't available in the image block. | ||
$post_id = get_the_ID(); | ||
} | ||
|
||
// TODO: Add logic to handle other meta types. | ||
if ( isset( $source_attrs['metaType'] ) ) { | ||
$meta_type = $source_attrs['metaType']; | ||
} else { | ||
$meta_type = 'post'; | ||
} | ||
|
||
// TODO: Add a filter/mechanism to limit the meta keys that can be used. | ||
return get_metadata( $meta_type, $post_id, $source_attrs['value'], true ); | ||
}; | ||
register_block_bindings_source( 'metadata', $metadata_source_callback ); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<?php | ||
/** | ||
* Add the metadata source to the block bindings API. | ||
* | ||
* @package gutenberg | ||
*/ | ||
|
||
if ( function_exists( 'register_block_bindings_source' ) ) { | ||
$pattern_source_callback = function ( $source_attrs, $block_content, $block, $block_instance ) { | ||
if ( ! _wp_array_get( $block_instance->attributes, array( 'metadata', 'id' ), false ) ) { | ||
return; | ||
} | ||
$block_id = $block_instance->attributes['metadata']['id']; | ||
return _wp_array_get( $block_instance->context, array( 'pattern/overrides', $block_id ), false ); | ||
}; | ||
register_block_bindings_source( 'pattern_attributes', $pattern_source_callback ); | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export { default as transformStyles } from './transform-styles'; | ||
export * from './block-variation-transforms'; | ||
export { default as getPxFromCssUnit } from './parse-css-unit-to-px'; | ||
export * from './update-bindings'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on #56704, this might not work for the heading block, but you could borrow from @kevin940726's approach in that PR of exploding the selector, at least until the HTML tag processor supports CSS selectors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for sharing! As part of this commit, I'm using that approach for supporting the different selectors we can have for the heading and the button.