From b19e148a0719a00c39bf8d7a2c2f63177de58349 Mon Sep 17 00:00:00 2001 From: gziolo Date: Thu, 8 Feb 2024 08:57:07 +0000 Subject: [PATCH] Editor: Introduce WP_Block_Bindings_Source class Abstracts the block bindings source array into a well-defined object. Fixes #60447. See #60282. Follow-up [57373]. Props czapla, santosguillamot, gziolo. Built from https://develop.svn.wordpress.org/trunk@57562 git-svn-id: http://core.svn.wordpress.org/trunk@57063 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/block-bindings.php | 8 +- .../class-wp-block-bindings-registry.php | 44 ++++++++-- .../class-wp-block-bindings-source.php | 88 +++++++++++++++++++ wp-includes/class-wp-block.php | 5 +- wp-includes/version.php | 2 +- wp-settings.php | 1 + 6 files changed, 133 insertions(+), 15 deletions(-) create mode 100644 wp-includes/class-wp-block-bindings-source.php diff --git a/wp-includes/block-bindings.php b/wp-includes/block-bindings.php index 7094313959..d1f0421621 100644 --- a/wp-includes/block-bindings.php +++ b/wp-includes/block-bindings.php @@ -88,7 +88,7 @@ * The callback has a mixed return type; it may return a string to override * the block's original value, null, false to remove an attribute, etc. * } - * @return array|false Source when the registration was successful, or `false` on failure. + * @return WP_Block_Bindings_Source|false Source when the registration was successful, or `false` on failure. */ function register_block_bindings_source( string $source_name, array $source_properties ) { return WP_Block_Bindings_Registry::get_instance()->register( $source_name, $source_properties ); @@ -100,7 +100,7 @@ function register_block_bindings_source( string $source_name, array $source_prop * @since 6.5.0 * * @param string $source_name Block bindings source name including namespace. - * @return array|false The unregistered block bindings source on success and `false` otherwise. + * @return WP_Block_Bindings_Source|false The unregistered block bindings source on success and `false` otherwise. */ function unregister_block_bindings_source( string $source_name ) { return WP_Block_Bindings_Registry::get_instance()->unregister( $source_name ); @@ -111,7 +111,7 @@ function unregister_block_bindings_source( string $source_name ) { * * @since 6.5.0 * - * @return array The array of registered block bindings sources. + * @return WP_Block_Bindings_Source[] The array of registered block bindings sources. */ function get_all_registered_block_bindings_sources() { return WP_Block_Bindings_Registry::get_instance()->get_all_registered(); @@ -123,7 +123,7 @@ function get_all_registered_block_bindings_sources() { * @since 6.5.0 * * @param string $source_name The name of the source. - * @return array|null The registered block bindings source, or `null` if it is not registered. + * @return WP_Block_Bindings_Source|null The registered block bindings source, or `null` if it is not registered. */ function get_block_bindings_source( string $source_name ) { return WP_Block_Bindings_Registry::get_instance()->get_registered( $source_name ); diff --git a/wp-includes/class-wp-block-bindings-registry.php b/wp-includes/class-wp-block-bindings-registry.php index edde1a0cb8..65f5f13c36 100644 --- a/wp-includes/class-wp-block-bindings-registry.php +++ b/wp-includes/class-wp-block-bindings-registry.php @@ -20,7 +20,7 @@ final class WP_Block_Bindings_Registry { * Holds the registered block bindings sources, keyed by source identifier. * * @since 6.5.0 - * @var array + * @var WP_Block_Bindings_Source[] */ private $sources = array(); @@ -66,7 +66,7 @@ final class WP_Block_Bindings_Registry { * The callback has a mixed return type; it may return a string to override * the block's original value, null, false to remove an attribute, etc. * } - * @return array|false Source when the registration was successful, or `false` on failure. + * @return WP_Block_Bindings_Source|false Source when the registration was successful, or `false` on failure. */ public function register( string $source_name, array $source_properties ) { if ( ! is_string( $source_name ) ) { @@ -107,8 +107,38 @@ final class WP_Block_Bindings_Registry { return false; } - $source = array_merge( - array( 'name' => $source_name ), + /* Validate that the source properties contain the label */ + if ( ! isset( $source_properties['label'] ) ) { + _doing_it_wrong( + __METHOD__, + __( 'The $source_properties must contain a "label".' ), + '6.5.0' + ); + return false; + } + + /* Validate that the source properties contain the get_value_callback */ + if ( ! isset( $source_properties['get_value_callback'] ) ) { + _doing_it_wrong( + __METHOD__, + __( 'The $source_properties must contain a "get_value_callback".' ), + '6.5.0' + ); + return false; + } + + /* Validate that the get_value_callback is a valid callback */ + if ( ! is_callable( $source_properties['get_value_callback'] ) ) { + _doing_it_wrong( + __METHOD__, + __( 'The "get_value_callback" parameter must be a valid callback.' ), + '6.5.0' + ); + return false; + } + + $source = new WP_Block_Bindings_Source( + $source_name, $source_properties ); @@ -123,7 +153,7 @@ final class WP_Block_Bindings_Registry { * @since 6.5.0 * * @param string $source_name Block bindings source name including namespace. - * @return array|false The unregistered block bindings source on success and `false` otherwise. + * @return WP_Block_Bindings_Source|false The unregistered block bindings source on success and `false` otherwise. */ public function unregister( string $source_name ) { if ( ! $this->is_registered( $source_name ) ) { @@ -147,7 +177,7 @@ final class WP_Block_Bindings_Registry { * * @since 6.5.0 * - * @return array The array of registered sources. + * @return WP_Block_Bindings_Source[] The array of registered sources. */ public function get_all_registered() { return $this->sources; @@ -159,7 +189,7 @@ final class WP_Block_Bindings_Registry { * @since 6.5.0 * * @param string $source_name The name of the source. - * @return array|null The registered block bindings source, or `null` if it is not registered. + * @return WP_Block_Bindings_Source|null The registered block bindings source, or `null` if it is not registered. */ public function get_registered( string $source_name ) { if ( ! $this->is_registered( $source_name ) ) { diff --git a/wp-includes/class-wp-block-bindings-source.php b/wp-includes/class-wp-block-bindings-source.php new file mode 100644 index 0000000000..c2a3d4f8ae --- /dev/null +++ b/wp-includes/class-wp-block-bindings-source.php @@ -0,0 +1,88 @@ +name = $name; + $this->label = $source_properties['label']; + $this->get_value_callback = $source_properties['get_value_callback']; + } + + /** + * Retrieves the value from the source. + * + * @since 6.5.0 + * + * @param array $source_args Array containing source arguments used to look up the override value, i.e. {"key": "foo"}. + * @param WP_Block $block_instance The block instance. + * @param string $attribute_name The name of the target attribute. + * + * @return mixed The value of the source. + */ + public function get_value( array $source_args, $block_instance, string $attribute_name ) { + return call_user_func_array( $this->get_value_callback, array( $source_args, $block_instance, $attribute_name ) ); + } + + /** + * Wakeup magic method. + * + * @since 6.5.0 + */ + public function __wakeup() { + throw new \LogicException( __CLASS__ . ' should never be unserialized' ); + } +} diff --git a/wp-includes/class-wp-block.php b/wp-includes/class-wp-block.php index 9f58a5fe45..a965ef1372 100644 --- a/wp-includes/class-wp-block.php +++ b/wp-includes/class-wp-block.php @@ -270,9 +270,8 @@ class WP_Block { continue; } - $source_callback = $block_binding_source['get_value_callback']; - $source_args = ! empty( $block_binding['args'] ) && is_array( $block_binding['args'] ) ? $block_binding['args'] : array(); - $source_value = call_user_func_array( $source_callback, array( $source_args, $this, $attribute_name ) ); + $source_args = ! empty( $block_binding['args'] ) && is_array( $block_binding['args'] ) ? $block_binding['args'] : array(); + $source_value = $block_binding_source->get_value( $source_args, $this, $attribute_name ); // If the value is not null, process the HTML based on the block and the attribute. if ( ! is_null( $source_value ) ) { diff --git a/wp-includes/version.php b/wp-includes/version.php index 27bd66fe80..d47249c599 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '6.5-alpha-57561'; +$wp_version = '6.5-alpha-57562'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema. diff --git a/wp-settings.php b/wp-settings.php index 228b4ac38a..6fa778d0cc 100644 --- a/wp-settings.php +++ b/wp-settings.php @@ -332,6 +332,7 @@ require ABSPATH . WPINC . '/sitemaps/class-wp-sitemaps-stylesheet.php'; require ABSPATH . WPINC . '/sitemaps/providers/class-wp-sitemaps-posts.php'; require ABSPATH . WPINC . '/sitemaps/providers/class-wp-sitemaps-taxonomies.php'; require ABSPATH . WPINC . '/sitemaps/providers/class-wp-sitemaps-users.php'; +require ABSPATH . WPINC . '/class-wp-block-bindings-source.php'; require ABSPATH . WPINC . '/class-wp-block-bindings-registry.php'; require ABSPATH . WPINC . '/class-wp-block-editor-context.php'; require ABSPATH . WPINC . '/class-wp-block-type.php';