diff --git a/wp-includes/block-bindings.php b/wp-includes/block-bindings.php index d1f0421621..cee00e246d 100644 --- a/wp-includes/block-bindings.php +++ b/wp-includes/block-bindings.php @@ -75,18 +75,19 @@ * @param array $source_properties { * The array of arguments that are used to register a source. * - * @type string $label The label of the source. - * @type callback $get_value_callback A callback executed when the source is processed during block rendering. - * The callback should have the following signature: + * @type string $label The label of the source. + * @type callback $get_value_callback A callback executed when the source is processed during block rendering. + * The callback should have the following signature: * - * `function ($source_args, $block_instance,$attribute_name): mixed` - * - @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 an attribute . - * 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. + * `function ($source_args, $block_instance,$attribute_name): mixed` + * - @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 an attribute . + * 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. + * @type array $uses_context (optional) Array of values to add to block `uses_context` needed by the source. * } * @return WP_Block_Bindings_Source|false Source when the registration was successful, or `false` on failure. */ diff --git a/wp-includes/block-bindings/pattern-overrides.php b/wp-includes/block-bindings/pattern-overrides.php index eabd874660..eae865e221 100644 --- a/wp-includes/block-bindings/pattern-overrides.php +++ b/wp-includes/block-bindings/pattern-overrides.php @@ -39,6 +39,7 @@ function _register_block_bindings_pattern_overrides_source() { array( 'label' => _x( 'Pattern Overrides', 'block bindings source' ), 'get_value_callback' => '_block_bindings_pattern_overrides_get_value', + 'uses_context' => array( 'pattern/overrides' ), ) ); } diff --git a/wp-includes/block-bindings/post-meta.php b/wp-includes/block-bindings/post-meta.php index 4be1ae96b7..5aa6bf048d 100644 --- a/wp-includes/block-bindings/post-meta.php +++ b/wp-includes/block-bindings/post-meta.php @@ -13,22 +13,20 @@ * @since 6.5.0 * @access private * - * @param array $source_args Array containing source arguments used to look up the override value. - * Example: array( "key" => "foo" ). + * @param array $source_args Array containing source arguments used to look up the override value. + * Example: array( "key" => "foo" ). + * @param WP_Block $block_instance The block instance. * @return mixed The value computed for the source. */ -function _block_bindings_post_meta_get_value( array $source_args ) { - if ( ! isset( $source_args['key'] ) ) { +function _block_bindings_post_meta_get_value( array $source_args, $block_instance ) { + if ( empty( $source_args['key'] ) ) { return null; } - // Use the postId attribute if available. - if ( isset( $source_args['postId'] ) ) { - $post_id = $source_args['postId']; - } else { - // $block_instance->context['postId'] is not available in the Image block. - $post_id = get_the_ID(); + if ( empty( $block_instance->context['postId'] ) ) { + return null; } + $post_id = $block_instance->context['postId']; // If a post isn't public, we need to prevent unauthorized users from accessing the post meta. $post = get_post( $post_id ); @@ -51,6 +49,7 @@ function _register_block_bindings_post_meta_source() { array( 'label' => _x( 'Post Meta', 'block bindings source' ), 'get_value_callback' => '_block_bindings_post_meta_get_value', + 'uses_context' => array( 'postId', 'postType' ), ) ); } diff --git a/wp-includes/class-wp-block-bindings-registry.php b/wp-includes/class-wp-block-bindings-registry.php index de6a9d89e4..6ec5ac81bb 100644 --- a/wp-includes/class-wp-block-bindings-registry.php +++ b/wp-includes/class-wp-block-bindings-registry.php @@ -32,6 +32,31 @@ final class WP_Block_Bindings_Registry { */ private static $instance = null; + /** + * Supported source properties that can be passed to the registered source. + * + * @since 6.5.0 + * @var array + */ + private $allowed_source_properties = array( + 'label', + 'get_value_callback', + 'uses_context', + ); + + /** + * Supported blocks that can use the block bindings API. + * + * @since 6.5.0 + * @var array + */ + private $supported_blocks = array( + 'core/paragraph', + 'core/heading', + 'core/image', + 'core/button', + ); + /** * Registers a new block bindings source. * @@ -53,18 +78,19 @@ final class WP_Block_Bindings_Registry { * @param array $source_properties { * The array of arguments that are used to register a source. * - * @type string $label The label of the source. - * @type callback $get_value_callback A callback executed when the source is processed during block rendering. - * The callback should have the following signature: + * @type string $label The label of the source. + * @type callback $get_value_callback A callback executed when the source is processed during block rendering. + * The callback should have the following signature: * - * `function ($source_args, $block_instance,$attribute_name): mixed` - * - @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. - * 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. + * `function ($source_args, $block_instance,$attribute_name): mixed` + * - @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. + * 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. + * @type array $uses_context (optional) Array of values to add to block `uses_context` needed by the source. * } * @return WP_Block_Bindings_Source|false Source when the registration was successful, or `false` on failure. */ @@ -107,7 +133,7 @@ final class WP_Block_Bindings_Registry { return false; } - /* Validate that the source properties contain the label */ + // Validates that the source properties contain the label. if ( ! isset( $source_properties['label'] ) ) { _doing_it_wrong( __METHOD__, @@ -117,7 +143,7 @@ final class WP_Block_Bindings_Registry { return false; } - /* Validate that the source properties contain the get_value_callback */ + // Validates that the source properties contain the get_value_callback. if ( ! isset( $source_properties['get_value_callback'] ) ) { _doing_it_wrong( __METHOD__, @@ -127,7 +153,7 @@ final class WP_Block_Bindings_Registry { return false; } - /* Validate that the get_value_callback is a valid callback */ + // Validates that the get_value_callback is a valid callback. if ( ! is_callable( $source_properties['get_value_callback'] ) ) { _doing_it_wrong( __METHOD__, @@ -137,6 +163,25 @@ final class WP_Block_Bindings_Registry { return false; } + // Validates that the uses_context parameter is an array. + if ( isset( $source_properties['uses_context'] ) && ! is_array( $source_properties['uses_context'] ) ) { + _doing_it_wrong( + __METHOD__, + __( 'The "uses_context" parameter must be an array.' ), + '6.5.0' + ); + return false; + } + + if ( ! empty( array_diff( array_keys( $source_properties ), $this->allowed_source_properties ) ) ) { + _doing_it_wrong( + __METHOD__, + __( 'The $source_properties array contains invalid properties.' ), + '6.5.0' + ); + return false; + } + $source = new WP_Block_Bindings_Source( $source_name, $source_properties @@ -144,6 +189,20 @@ final class WP_Block_Bindings_Registry { $this->sources[ $source_name ] = $source; + // Adds `uses_context` defined by block bindings sources. + add_filter( + 'get_block_type_uses_context', + function ( $uses_context, $block_type ) use ( $source ) { + if ( ! in_array( $block_type->name, $this->supported_blocks, true ) || empty( $source->uses_context ) ) { + return $uses_context; + } + // Use array_values to reset the array keys. + return array_values( array_unique( array_merge( $uses_context, $source->uses_context ) ) ); + }, + 10, + 2 + ); + return $source; } diff --git a/wp-includes/class-wp-block-bindings-source.php b/wp-includes/class-wp-block-bindings-source.php index c2a3d4f8ae..036e17c3dd 100644 --- a/wp-includes/class-wp-block-bindings-source.php +++ b/wp-includes/class-wp-block-bindings-source.php @@ -45,6 +45,14 @@ final class WP_Block_Bindings_Source { */ private $get_value_callback; + /** + * The context added to the blocks needed by the source. + * + * @since 6.5.0 + * @var array|null + */ + public $uses_context = null; + /** * Constructor. * @@ -57,9 +65,10 @@ final class WP_Block_Bindings_Source { * @param array $source_properties The properties of the source. */ public function __construct( string $name, array $source_properties ) { - $this->name = $name; - $this->label = $source_properties['label']; - $this->get_value_callback = $source_properties['get_value_callback']; + $this->name = $name; + foreach ( $source_properties as $property_name => $property_value ) { + $this->$property_name = $property_value; + } } /** diff --git a/wp-includes/class-wp-block-type.php b/wp-includes/class-wp-block-type.php index 63496d4102..3242653528 100644 --- a/wp-includes/class-wp-block-type.php +++ b/wp-includes/class-wp-block-type.php @@ -180,7 +180,7 @@ class WP_Block_Type { * @since 5.5.0 * @var string[] */ - public $uses_context = array(); + private $uses_context = array(); /** * Context provided by blocks of this type. @@ -366,6 +366,10 @@ class WP_Block_Type { return $this->get_variations(); } + if ( 'uses_context' === $name ) { + return $this->get_uses_context(); + } + if ( ! in_array( $name, $this->deprecated_properties, true ) ) { return; } @@ -394,7 +398,7 @@ class WP_Block_Type { * or false otherwise. */ public function __isset( $name ) { - if ( 'variations' === $name ) { + if ( in_array( $name, array( 'variations', 'uses_context' ), true ) ) { return true; } @@ -417,11 +421,6 @@ class WP_Block_Type { * @param mixed $value Property value. */ public function __set( $name, $value ) { - if ( 'variations' === $name ) { - $this->variations = $value; - return; - } - if ( ! in_array( $name, $this->deprecated_properties, true ) ) { $this->{$name} = $value; return; @@ -616,4 +615,23 @@ class WP_Block_Type { */ return apply_filters( 'get_block_type_variations', $this->variations, $this ); } + + /** + * Get block uses context. + * + * @since 6.5.0 + * + * @return array[] + */ + public function get_uses_context() { + /** + * Filters the registered uses context for a block type. + * + * @since 6.5.0 + * + * @param array $uses_context Array of registered uses context for a block type. + * @param WP_Block_Type $block_type The full block type object. + */ + return apply_filters( 'get_block_type_uses_context', $this->uses_context, $this ); + } } diff --git a/wp-includes/class-wp-block.php b/wp-includes/class-wp-block.php index 0145ba4369..8d11eba20d 100644 --- a/wp-includes/class-wp-block.php +++ b/wp-includes/class-wp-block.php @@ -231,23 +231,19 @@ class WP_Block { * @return array The computed block attributes for the provided block bindings. */ private function process_block_bindings() { - $parsed_block = $this->parsed_block; - - $computed_attributes = array(); - - // Allowed blocks that support block bindings. - // TODO: Look for a mechanism to opt-in for this. Maybe adding a property to block attributes? - $allowed_blocks = array( + $parsed_block = $this->parsed_block; + $computed_attributes = array(); + $supported_block_attributes = array( 'core/paragraph' => array( 'content' ), 'core/heading' => array( 'content' ), 'core/image' => array( 'url', 'title', 'alt' ), 'core/button' => array( 'url', 'text', 'linkTarget', 'rel' ), ); - // If the block doesn't have the bindings property, isn't one of the allowed + // If the block doesn't have the bindings property, isn't one of the supported // block types, or the bindings property is not an array, return the block content. if ( - ! isset( $allowed_blocks[ $this->name ] ) || + ! isset( $supported_block_attributes[ $this->name ] ) || empty( $parsed_block['attrs']['metadata']['bindings'] ) || ! is_array( $parsed_block['attrs']['metadata']['bindings'] ) ) { @@ -255,8 +251,8 @@ class WP_Block { } foreach ( $parsed_block['attrs']['metadata']['bindings'] as $attribute_name => $block_binding ) { - // If the attribute is not in the allowed list, process next attribute. - if ( ! in_array( $attribute_name, $allowed_blocks[ $this->name ], true ) ) { + // If the attribute is not in the supported list, process next attribute. + if ( ! in_array( $attribute_name, $supported_block_attributes[ $this->name ], true ) ) { continue; } // If no source is provided, or that source is not registered, process next attribute. diff --git a/wp-includes/version.php b/wp-includes/version.php index 09d99a280c..e203076629 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '6.5-beta1-57640'; +$wp_version = '6.5-beta1-57641'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.