--- a/wp/wp-includes/class-wp-block.php Fri Sep 05 18:40:08 2025 +0200
+++ b/wp/wp-includes/class-wp-block.php Fri Sep 05 18:52:52 2025 +0200
@@ -56,7 +56,7 @@
* @var array
* @access protected
*/
- protected $available_context;
+ protected $available_context = array();
/**
* Block type registry.
@@ -114,7 +114,7 @@
* @since 5.5.0
*
* @param array $block {
- * A representative array of a single parsed block object. See WP_Block_Parser_Block.
+ * An associative array of a single parsed block object. See WP_Block_Parser_Block.
*
* @type string $blockName Name of block.
* @type array $attrs Attributes from block comment delimiters.
@@ -140,6 +140,28 @@
$this->available_context = $available_context;
+ $this->refresh_context_dependents();
+ }
+
+ /**
+ * Updates the context for the current block and its inner blocks.
+ *
+ * The method updates the context of inner blocks, if any, by passing down
+ * any context values the block provides (`provides_context`).
+ *
+ * If the block has inner blocks, the method recursively processes them by creating new instances of `WP_Block`
+ * for each inner block and updating their context based on the block's `provides_context` property.
+ *
+ * @since 6.8.0
+ */
+ public function refresh_context_dependents() {
+ /*
+ * Merging the `$context` property here is not ideal, but for now needs to happen because of backward compatibility.
+ * Ideally, the `$context` property itself would not be filterable directly and only the `$available_context` would be filterable.
+ * However, this needs to be separately explored whether it's possible without breakage.
+ */
+ $this->available_context = array_merge( $this->available_context, $this->context );
+
if ( ! empty( $this->block_type->uses_context ) ) {
foreach ( $this->block_type->uses_context as $context_name ) {
if ( array_key_exists( $context_name, $this->available_context ) ) {
@@ -148,7 +170,23 @@
}
}
- if ( ! empty( $block['innerBlocks'] ) ) {
+ $this->refresh_parsed_block_dependents();
+ }
+
+ /**
+ * Updates the parsed block content for the current block and its inner blocks.
+ *
+ * This method sets the `inner_html` and `inner_content` properties of the block based on the parsed
+ * block content provided during initialization. It ensures that the block instance reflects the
+ * most up-to-date content for both the inner HTML and any string fragments around inner blocks.
+ *
+ * If the block has inner blocks, this method initializes a new `WP_Block_List` for them, ensuring the
+ * correct content and context are updated for each nested block.
+ *
+ * @since 6.8.0
+ */
+ public function refresh_parsed_block_dependents() {
+ if ( ! empty( $this->parsed_block['innerBlocks'] ) ) {
$child_context = $this->available_context;
if ( ! empty( $this->block_type->provides_context ) ) {
@@ -159,15 +197,15 @@
}
}
- $this->inner_blocks = new WP_Block_List( $block['innerBlocks'], $child_context, $registry );
+ $this->inner_blocks = new WP_Block_List( $this->parsed_block['innerBlocks'], $child_context, $this->registry );
}
- if ( ! empty( $block['innerHTML'] ) ) {
- $this->inner_html = $block['innerHTML'];
+ if ( ! empty( $this->parsed_block['innerHTML'] ) ) {
+ $this->inner_html = $this->parsed_block['innerHTML'];
}
- if ( ! empty( $block['innerContent'] ) ) {
- $this->inner_content = $block['innerContent'];
+ if ( ! empty( $this->parsed_block['innerContent'] ) ) {
+ $this->inner_content = $this->parsed_block['innerContent'];
}
}
@@ -237,6 +275,7 @@
*
* @since 6.5.0
* @since 6.6.0 Handle the `__default` attribute for pattern overrides.
+ * @since 6.7.0 Return any updated bindings metadata in the computed attributes.
*
* @return array The computed block attributes for the provided block bindings.
*/
@@ -284,6 +323,14 @@
: array( 'source' => 'core/pattern-overrides' );
}
$bindings = $updated_bindings;
+ /*
+ * Update the bindings metadata of the computed attributes.
+ * This ensures the block receives the expanded __default binding metadata when it renders.
+ */
+ $computed_attributes['metadata'] = array_merge(
+ $parsed_block['attrs']['metadata'],
+ array( 'bindings' => $bindings )
+ );
}
foreach ( $bindings as $attribute_name => $block_binding ) {
@@ -301,6 +348,15 @@
continue;
}
+ // Adds the necessary context defined by the source.
+ if ( ! empty( $block_binding_source->uses_context ) ) {
+ foreach ( $block_binding_source->uses_context as $context_name ) {
+ if ( array_key_exists( $context_name, $this->available_context ) ) {
+ $this->context[ $context_name ] = $this->available_context[ $context_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 );
@@ -356,7 +412,7 @@
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(
+ if ( strcasecmp( $block_reader->get_tag(), $selector ) === 0 || $block_reader->next_tag(
array(
'tag_name' => $selector,
)
@@ -488,7 +544,8 @@
if ( ! is_null( $pre_render ) ) {
$block_content .= $pre_render;
} else {
- $source_block = $inner_block->parsed_block;
+ $source_block = $inner_block->parsed_block;
+ $inner_block_context = $inner_block->context;
/** This filter is documented in wp-includes/blocks.php */
$inner_block->parsed_block = apply_filters( 'render_block_data', $inner_block->parsed_block, $source_block, $parent_block );
@@ -496,6 +553,16 @@
/** This filter is documented in wp-includes/blocks.php */
$inner_block->context = apply_filters( 'render_block_context', $inner_block->context, $inner_block->parsed_block, $parent_block );
+ /*
+ * The `refresh_context_dependents()` method already calls `refresh_parsed_block_dependents()`.
+ * Therefore the second condition is irrelevant if the first one is satisfied.
+ */
+ if ( $inner_block->context !== $inner_block_context ) {
+ $inner_block->refresh_context_dependents();
+ } elseif ( $inner_block->parsed_block !== $source_block ) {
+ $inner_block->refresh_parsed_block_dependents();
+ }
+
$block_content .= $inner_block->render();
}
@@ -541,6 +608,11 @@
}
}
+ /*
+ * For Core blocks, these styles are only enqueued if `wp_should_load_separate_core_block_assets()` returns
+ * true. Otherwise these `wp_enqueue_style()` calls will not have any effect, as the Core blocks are relying on
+ * the combined 'wp-block-library' stylesheet instead, which is unconditionally enqueued.
+ */
if ( ( ! empty( $this->block_type->style_handles ) ) ) {
foreach ( $this->block_type->style_handles as $style_handle ) {
wp_enqueue_style( $style_handle );