-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Block Bindings API: Add block bindings PHP registration mechanisms an…
…d "Post meta" source under the experimental flag (#57249) * Change block bindings experiment name * Remove old custom fields UI * Add block bindings PHP logic * Add pattern source * Add post meta source * Adapt partially synced patterns experiment * Add domain to the translations in sources * Remove unused post_meta attrs * Change variable name * Remove a couple of comments * Add image alt to permitted attributes * Rename variables and clean up code * Fix bug wherein original pattern values were not being displayed * fix typo * Format a comment * fix comment indentation * remove the .vscode/settings.json file that sneaked in * Sync with added support for multiple attributes in patterns * Remove block supports requirement for partial syncing * Remove __experimentalBlockBindings supports from paragraph * Simplify source callback and update comments * Remove erroneous comment * Revert "Remove block supports requirement for partial syncing" This reverts commit 7fb646c. * Revert "Remove __experimentalBlockBindings supports from paragraph" This reverts commit 34e3f29. * Remove block supports dependency * Update signature and docblock of register function * Empty-Commit * Update the PHPDoc string --------- Co-authored-by: Ricardo Artemio Morales <[email protected]> Co-authored-by: Michal Czaplinski <[email protected]>
- Loading branch information
1 parent
b64eec7
commit cd548af
Showing
16 changed files
with
317 additions
and
279 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
<?php | ||
/** | ||
* Define the mechanism to replace 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. | ||
switch ( $block_type->attributes[ $block_attr ]['source'] ) { | ||
case 'html': | ||
case 'rich-text': | ||
$block_reader = new WP_HTML_Tag_Processor( $block_content ); | ||
|
||
// TODO: Support for CSS selectors whenever they are ready in the HTML API. | ||
// In the meantime, support comma-separated selectors by exploding them into an array. | ||
$selectors = explode( ',', $block_type->attributes[ $block_attr ]['selector'] ); | ||
// Add a bookmark to the first tag to be able to iterate over the selectors. | ||
$block_reader->next_tag(); | ||
$block_reader->set_bookmark( 'iterate-selectors' ); | ||
|
||
// TODO: This shouldn't be needed when the `set_inner_html` function is ready. | ||
// Store the parent tag and its attributes to be able to restore them later in the button. | ||
// The button block has a wrapper while the paragraph and heading blocks don't. | ||
if ( 'core/button' === $block_name ) { | ||
$button_wrapper = $block_reader->get_tag(); | ||
$button_wrapper_attribute_names = $block_reader->get_attribute_names_with_prefix( '' ); | ||
$button_wrapper_attrs = array(); | ||
foreach ( $button_wrapper_attribute_names as $name ) { | ||
$button_wrapper_attrs[ $name ] = $block_reader->get_attribute( $name ); | ||
} | ||
} | ||
|
||
foreach ( $selectors as $selector ) { | ||
// If the parent tag, or any of its children, matches the selector, replace the HTML. | ||
if ( strcasecmp( $block_reader->get_tag( $selector ), $selector ) === 0 || $block_reader->next_tag( | ||
array( | ||
'tag_name' => $selector, | ||
) | ||
) ) { | ||
$block_reader->release_bookmark( 'iterate-selectors' ); | ||
|
||
// TODO: Use `set_inner_html` method whenever it's ready in the HTML API. | ||
// Until then, it is hardcoded for the paragraph, heading, and button blocks. | ||
// Store the tag and its attributes to be able to restore them later. | ||
$selector_attribute_names = $block_reader->get_attribute_names_with_prefix( '' ); | ||
$selector_attrs = array(); | ||
foreach ( $selector_attribute_names as $name ) { | ||
$selector_attrs[ $name ] = $block_reader->get_attribute( $name ); | ||
} | ||
$selector_markup = "<$selector>" . esc_html( $source_value ) . "</$selector>"; | ||
$amended_content = new WP_HTML_Tag_Processor( $selector_markup ); | ||
$amended_content->next_tag(); | ||
foreach ( $selector_attrs as $attribute_key => $attribute_value ) { | ||
$amended_content->set_attribute( $attribute_key, $attribute_value ); | ||
} | ||
if ( 'core/paragraph' === $block_name || 'core/heading' === $block_name ) { | ||
return $amended_content->get_updated_html(); | ||
} | ||
if ( 'core/button' === $block_name ) { | ||
$button_markup = "<$button_wrapper>{$amended_content->get_updated_html()}</$button_wrapper>"; | ||
$amended_button = new WP_HTML_Tag_Processor( $button_markup ); | ||
$amended_button->next_tag(); | ||
foreach ( $button_wrapper_attrs as $attribute_key => $attribute_value ) { | ||
$amended_button->set_attribute( $attribute_key, $attribute_value ); | ||
} | ||
return $amended_button->get_updated_html(); | ||
} | ||
} else { | ||
$block_reader->seek( 'iterate-selectors' ); | ||
} | ||
} | ||
$block_reader->release_bookmark( 'iterate-selectors' ); | ||
return $block_content; | ||
|
||
case 'attribute': | ||
$amended_content = new WP_HTML_Tag_Processor( $block_content ); | ||
if ( ! $amended_content->next_tag( | ||
array( | ||
// TODO: build the query from CSS selector. | ||
'tag_name' => $block_type->attributes[ $block_attr ]['selector'], | ||
) | ||
) ) { | ||
return $block_content; | ||
} | ||
$amended_content->set_attribute( $block_type->attributes[ $block_attr ]['attribute'], esc_attr( $source_value ) ); | ||
return $amended_content->get_updated_html(); | ||
break; | ||
|
||
default: | ||
return $block_content; | ||
break; | ||
} | ||
return; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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-block-bindings', $gutenberg_experiments ) ) { | ||
require_once __DIR__ . '/sources/post-meta.php'; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?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 string $label The label of the source. | ||
* @param callable(object, object, string): string $apply - The callback executed when the source is processed during block rendering. | ||
* - object $source_attrs: Object containing source ID used to look up the override value, i.e. {"value": "{ID}"}. | ||
* - object $block_instance: The block instance. | ||
* - string $attribute_name: The name of an attribute used to retrieve an override value from the block context. | ||
* The callable should return a string that will be used to override the block's original value. | ||
* | ||
* | ||
* @return void | ||
*/ | ||
function register_block_bindings_source( $source_name, $label, $apply ) { | ||
global $block_bindings_sources; | ||
$block_bindings_sources[ $source_name ] = array( | ||
'label' => $label, | ||
'apply' => $apply, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?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_instance, $attribute_name ) { | ||
if ( ! _wp_array_get( $block_instance->attributes, array( 'metadata', 'id' ), false ) ) { | ||
return null; | ||
} | ||
$block_id = $block_instance->attributes['metadata']['id']; | ||
return _wp_array_get( $block_instance->context, array( 'pattern/overrides', $block_id, $attribute_name ), null ); | ||
}; | ||
register_block_bindings_source( | ||
'pattern_attributes', | ||
__( 'Pattern Attributes', 'gutenberg' ), | ||
$pattern_source_callback | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<?php | ||
/** | ||
* Add the post_meta source to the block bindings API. | ||
* | ||
* @package gutenberg | ||
*/ | ||
|
||
if ( function_exists( 'register_block_bindings_source' ) ) { | ||
$post_meta_source_callback = function ( $source_attrs ) { | ||
// Use the postId attribute if available | ||
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(); | ||
} | ||
|
||
return get_post_meta( $post_id, $source_attrs['value'], true ); | ||
}; | ||
register_block_bindings_source( | ||
'post_meta', | ||
__( 'Post Meta', 'gutenberg' ), | ||
$post_meta_source_callback | ||
); | ||
} |
Oops, something went wrong.