@@ -56,7 +56,7 @@ class WP_Block {
5656 * @var array
5757 * @access protected
5858 */
59- protected $ available_context ;
59+ protected $ available_context = array () ;
6060
6161 /**
6262 * Block type registry.
@@ -140,6 +140,28 @@ public function __construct( $block, $available_context = array(), $registry = n
140140
141141 $ this ->available_context = $ available_context ;
142142
143+ $ this ->refresh_context_dependents ();
144+ }
145+
146+ /**
147+ * Updates the context for the current block and its inner blocks.
148+ *
149+ * The method updates the context of inner blocks, if any, by passing down
150+ * any context values the block provides (`provides_context`).
151+ *
152+ * If the block has inner blocks, the method recursively processes them by creating new instances of `WP_Block`
153+ * for each inner block and updating their context based on the block's `provides_context` property.
154+ *
155+ * @since 6.8.0
156+ */
157+ public function refresh_context_dependents () {
158+ /*
159+ * Merging the `$context` property here is not ideal, but for now needs to happen because of backward compatibility.
160+ * Ideally, the `$context` property itself would not be filterable directly and only the `$available_context` would be filterable.
161+ * However, this needs to be separately explored whether it's possible without breakage.
162+ */
163+ $ this ->available_context = array_merge ( $ this ->available_context , $ this ->context );
164+
143165 if ( ! empty ( $ this ->block_type ->uses_context ) ) {
144166 foreach ( $ this ->block_type ->uses_context as $ context_name ) {
145167 if ( array_key_exists ( $ context_name , $ this ->available_context ) ) {
@@ -148,7 +170,23 @@ public function __construct( $block, $available_context = array(), $registry = n
148170 }
149171 }
150172
151- if ( ! empty ( $ block ['innerBlocks ' ] ) ) {
173+ $ this ->refresh_parsed_block_dependents ();
174+ }
175+
176+ /**
177+ * Updates the parsed block content for the current block and its inner blocks.
178+ *
179+ * This method sets the `inner_html` and `inner_content` properties of the block based on the parsed
180+ * block content provided during initialization. It ensures that the block instance reflects the
181+ * most up-to-date content for both the inner HTML and any string fragments around inner blocks.
182+ *
183+ * If the block has inner blocks, this method initializes a new `WP_Block_List` for them, ensuring the
184+ * correct content and context are updated for each nested block.
185+ *
186+ * @since 6.8.0
187+ */
188+ public function refresh_parsed_block_dependents () {
189+ if ( ! empty ( $ this ->parsed_block ['innerBlocks ' ] ) ) {
152190 $ child_context = $ this ->available_context ;
153191
154192 if ( ! empty ( $ this ->block_type ->provides_context ) ) {
@@ -159,15 +197,15 @@ public function __construct( $block, $available_context = array(), $registry = n
159197 }
160198 }
161199
162- $ this ->inner_blocks = new WP_Block_List ( $ block ['innerBlocks ' ], $ child_context , $ registry );
200+ $ this ->inner_blocks = new WP_Block_List ( $ this -> parsed_block ['innerBlocks ' ], $ child_context , $ this -> registry );
163201 }
164202
165- if ( ! empty ( $ block ['innerHTML ' ] ) ) {
166- $ this ->inner_html = $ block ['innerHTML ' ];
203+ if ( ! empty ( $ this -> parsed_block ['innerHTML ' ] ) ) {
204+ $ this ->inner_html = $ this -> parsed_block ['innerHTML ' ];
167205 }
168206
169- if ( ! empty ( $ block ['innerContent ' ] ) ) {
170- $ this ->inner_content = $ block ['innerContent ' ];
207+ if ( ! empty ( $ this -> parsed_block ['innerContent ' ] ) ) {
208+ $ this ->inner_content = $ this -> parsed_block ['innerContent ' ];
171209 }
172210 }
173211
@@ -506,14 +544,25 @@ public function render( $options = array() ) {
506544 if ( ! is_null ( $ pre_render ) ) {
507545 $ block_content .= $ pre_render ;
508546 } else {
509- $ source_block = $ inner_block ->parsed_block ;
547+ $ source_block = $ inner_block ->parsed_block ;
548+ $ inner_block_context = $ inner_block ->context ;
510549
511550 /** This filter is documented in wp-includes/blocks.php */
512551 $ inner_block ->parsed_block = apply_filters ( 'render_block_data ' , $ inner_block ->parsed_block , $ source_block , $ parent_block );
513552
514553 /** This filter is documented in wp-includes/blocks.php */
515554 $ inner_block ->context = apply_filters ( 'render_block_context ' , $ inner_block ->context , $ inner_block ->parsed_block , $ parent_block );
516555
556+ /*
557+ * The `refresh_context_dependents()` method already calls `refresh_parsed_block_dependents()`.
558+ * Therefore the second condition is irrelevant if the first one is satisfied.
559+ */
560+ if ( $ inner_block ->context !== $ inner_block_context ) {
561+ $ inner_block ->refresh_context_dependents ();
562+ } elseif ( $ inner_block ->parsed_block !== $ source_block ) {
563+ $ inner_block ->refresh_parsed_block_dependents ();
564+ }
565+
517566 $ block_content .= $ inner_block ->render ();
518567 }
519568
0 commit comments