From b5451467968b3d2d7c987cbb2e44841bdf902ad4 Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Fri, 17 Nov 2023 17:27:47 +0100 Subject: [PATCH 01/27] Initial commit --- .../class-wp-directive-processor.php | 55 ++++++++++++++++- .../directive-processing.php | 61 +++++++++++++++++++ 2 files changed, 114 insertions(+), 2 deletions(-) diff --git a/lib/experimental/interactivity-api/class-wp-directive-processor.php b/lib/experimental/interactivity-api/class-wp-directive-processor.php index e717b2e553943..253d2d98306cc 100644 --- a/lib/experimental/interactivity-api/class-wp-directive-processor.php +++ b/lib/experimental/interactivity-api/class-wp-directive-processor.php @@ -23,9 +23,9 @@ class WP_Directive_Processor extends Gutenberg_HTML_Tag_Processor_6_4 { /** - * An array of root blocks. + * A string containing the main root block. * - * @var array + * @var string */ public static $root_block = null; @@ -70,6 +70,57 @@ public static function has_root_block() { } + + /** + * A string containing the main children of interactive. + * + * @var string + */ + public static $children_of_interactive_block = null; + + + /** + * Add a root block to the variable. + * + * @param array $block The block to add. + * + * @return void + */ + public static function mark_children_of_interactive_block( $block ) { + self::$children_of_interactive_block = md5( serialize( $block ) ); + } + + /** + * Remove a root block to the variable. + * + * @return void + */ + public static function unmark_children_of_interactive_block() { + self::$children_of_interactive_block = null; + } + + /** + * Check if block is a root block. + * + * @param array $block The block to check. + * + * @return bool True if block is a root block, false otherwise. + */ + public static function is_marked_as_children_of_interactive_block( $block ) { + return md5( serialize( $block ) ) === self::$children_of_interactive_block; + } + + /** + * Check if a root block has already been defined. + * + * @return bool True if block is a root block, false otherwise. + */ + public static function has_children_of_interactive_block() { + return isset( self::$children_of_interactive_block ); + } + + + /** * Find the matching closing tag for an opening tag. * diff --git a/lib/experimental/interactivity-api/directive-processing.php b/lib/experimental/interactivity-api/directive-processing.php index 064fc8ea62cbb..09c68a75ad355 100644 --- a/lib/experimental/interactivity-api/directive-processing.php +++ b/lib/experimental/interactivity-api/directive-processing.php @@ -7,6 +7,8 @@ * @subpackage Interactivity API */ +global $children_of_interactive_block; +$children_of_interactive_block = array(); /** * Mark if the block is a root block. Checks that there is already a root block * in order not to mark template-parts or synced patterns as root blocks, where @@ -56,6 +58,65 @@ function gutenberg_process_directives_in_root_blocks( $block_content, $block ) { } add_filter( 'render_block', 'gutenberg_process_directives_in_root_blocks', 10, 2 ); +/** + * Creates a stack of interactive block children. + * + * @param array $parsed_block The parsed block. + * @param array $source_block The source block. + * @param WP_Block $parent_block The parent block. + */ +function gutenberg_mark_interactive_block_children( $parsed_block, $source_block, $parent_block ) { + if ( + isset( $parent_block ) && + isset( $parent_block->block_type->supports['interactivity'] ) && + $parent_block->block_type->supports['interactivity'] + ) { + WP_Directive_Processor::mark_children_of_interactive_block( $source_block ); + } + return $parsed_block; +} +add_filter( 'render_block_data', 'gutenberg_mark_interactive_block_children', 100, 3 ); + + +/** + * Add a marker indicating if the block is interactive or not. + * core/interactivity-wrapper if it is interactive. + * core/non-interactivity-wrapper if it is not interactive. + * + * @param string $block_content The block content. + * @param array $block The full block, including name and attributes. + * @param WP_Block $block_instance The block instance. + */ +function gutenberg_mark_block_interactivity( $block_content, $block, $block_instance ) { + if ( + isset( $block_instance->block_type->supports['interactivity'] ) && + $block_instance->block_type->supports['interactivity'] + ) { + WP_Directive_Processor::unmark_children_of_interactive_block(); + // Mark interactive blocks so we can process them later. + return get_comment_delimited_block_content( + 'core/interactivity-wrapper', + array( + 'blockName' => $block['blockName'], + // We can put extra information about the block here. + ), + $block_content + ); + } elseif ( WP_Directive_Processor::is_marked_as_children_of_interactive_block( $block ) ) { + // Mark children of interactive blocks that are not interactive themselves + // to so we can skip them later. + WP_Directive_Processor::unmark_children_of_interactive_block(); + return get_comment_delimited_block_content( + 'core/non-interactivity-wrapper', + array(), + $block_content + ); + } + + return $block_content; +} + +add_filter( 'render_block', 'gutenberg_mark_block_interactivity', 10, 3 ); /** * Resolve the reference using the store and the context from the provided path. From 296f237589b7f646325c1e07775c8a1f234b5861 Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Sat, 18 Nov 2023 13:33:09 +0100 Subject: [PATCH 02/27] It works, but is stripping comments --- .../class-wp-directive-processor.php | 16 +++++++++------- .../interactivity-api/directive-processing.php | 9 ++++----- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/experimental/interactivity-api/class-wp-directive-processor.php b/lib/experimental/interactivity-api/class-wp-directive-processor.php index 253d2d98306cc..cb00a0231bd42 100644 --- a/lib/experimental/interactivity-api/class-wp-directive-processor.php +++ b/lib/experimental/interactivity-api/class-wp-directive-processor.php @@ -72,11 +72,11 @@ public static function has_root_block() { /** - * A string containing the main children of interactive. + * An array containing the main children of interactive. * - * @var string + * @var array */ - public static $children_of_interactive_block = null; + public static $children_of_interactive_block = array(); /** @@ -87,16 +87,18 @@ public static function has_root_block() { * @return void */ public static function mark_children_of_interactive_block( $block ) { - self::$children_of_interactive_block = md5( serialize( $block ) ); + self::$children_of_interactive_block[] = md5( serialize( $block ) ); } /** * Remove a root block to the variable. * + * @param array $block The block to remove. + * * @return void */ - public static function unmark_children_of_interactive_block() { - self::$children_of_interactive_block = null; + public static function unmark_children_of_interactive_block( $block ) { + self::$children_of_interactive_block = array_diff( self::$children_of_interactive_block, array( md5( serialize( $block ) ) ) ); } /** @@ -107,7 +109,7 @@ public static function unmark_children_of_interactive_block() { * @return bool True if block is a root block, false otherwise. */ public static function is_marked_as_children_of_interactive_block( $block ) { - return md5( serialize( $block ) ) === self::$children_of_interactive_block; + return in_array( md5( serialize( $block ) ), self::$children_of_interactive_block, true ); } /** diff --git a/lib/experimental/interactivity-api/directive-processing.php b/lib/experimental/interactivity-api/directive-processing.php index 09c68a75ad355..812c9c6f6afe0 100644 --- a/lib/experimental/interactivity-api/directive-processing.php +++ b/lib/experimental/interactivity-api/directive-processing.php @@ -92,7 +92,6 @@ function gutenberg_mark_block_interactivity( $block_content, $block, $block_inst isset( $block_instance->block_type->supports['interactivity'] ) && $block_instance->block_type->supports['interactivity'] ) { - WP_Directive_Processor::unmark_children_of_interactive_block(); // Mark interactive blocks so we can process them later. return get_comment_delimited_block_content( 'core/interactivity-wrapper', @@ -105,10 +104,10 @@ function gutenberg_mark_block_interactivity( $block_content, $block, $block_inst } elseif ( WP_Directive_Processor::is_marked_as_children_of_interactive_block( $block ) ) { // Mark children of interactive blocks that are not interactive themselves // to so we can skip them later. - WP_Directive_Processor::unmark_children_of_interactive_block(); - return get_comment_delimited_block_content( - 'core/non-interactivity-wrapper', - array(), + WP_Directive_Processor::unmark_children_of_interactive_block( $block ); + return sprintf( + '
%s
', + // '%s', $block_content ); } From 4adc34c8787a69a1c12ee413b54d364b30d25c23 Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Sat, 18 Nov 2023 13:36:39 +0100 Subject: [PATCH 03/27] Added an extra return for debugging --- .../directive-processing.php | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/experimental/interactivity-api/directive-processing.php b/lib/experimental/interactivity-api/directive-processing.php index 812c9c6f6afe0..b50b0dda3b0a5 100644 --- a/lib/experimental/interactivity-api/directive-processing.php +++ b/lib/experimental/interactivity-api/directive-processing.php @@ -105,11 +105,24 @@ function gutenberg_mark_block_interactivity( $block_content, $block, $block_inst // Mark children of interactive blocks that are not interactive themselves // to so we can skip them later. WP_Directive_Processor::unmark_children_of_interactive_block( $block ); - return sprintf( - '
%s
', - // '%s', + return get_comment_delimited_block_content( + 'core/interactivity-wrapper', + array( + 'blockName' => $block['blockName'], + // We can put extra information about the block here. + ), $block_content ); + /** + * Debugging purposes only. + */ + return sprintf( + '
%s
', + // '%s', + // $block['blockName'], + $block_content + ); + } return $block_content; From b7185a3c3ff646ce1d139dfdf78230fc0d2383a0 Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Sat, 18 Nov 2023 14:10:55 +0100 Subject: [PATCH 04/27] Refactor to use string instead of arrays to compare --- .../class-wp-directive-processor.php | 30 +++++-------------- .../directive-processing.php | 21 ++++++------- 2 files changed, 18 insertions(+), 33 deletions(-) diff --git a/lib/experimental/interactivity-api/class-wp-directive-processor.php b/lib/experimental/interactivity-api/class-wp-directive-processor.php index cb00a0231bd42..31037f1981a89 100644 --- a/lib/experimental/interactivity-api/class-wp-directive-processor.php +++ b/lib/experimental/interactivity-api/class-wp-directive-processor.php @@ -69,15 +69,12 @@ public static function has_root_block() { return isset( self::$root_block ); } - - /** - * An array containing the main children of interactive. + * A string containing the main children of interactive. * - * @var array + * @var string */ - public static $children_of_interactive_block = array(); - + public static $children_of_interactive_block = null; /** * Add a root block to the variable. @@ -87,18 +84,16 @@ public static function has_root_block() { * @return void */ public static function mark_children_of_interactive_block( $block ) { - self::$children_of_interactive_block[] = md5( serialize( $block ) ); + self::$children_of_interactive_block = md5( serialize( $block ) ); } /** * Remove a root block to the variable. * - * @param array $block The block to remove. - * * @return void */ - public static function unmark_children_of_interactive_block( $block ) { - self::$children_of_interactive_block = array_diff( self::$children_of_interactive_block, array( md5( serialize( $block ) ) ) ); + public static function unmark_children_of_interactive_block() { + self::$children_of_interactive_block = null; } /** @@ -109,20 +104,9 @@ public static function unmark_children_of_interactive_block( $block ) { * @return bool True if block is a root block, false otherwise. */ public static function is_marked_as_children_of_interactive_block( $block ) { - return in_array( md5( serialize( $block ) ), self::$children_of_interactive_block, true ); - } - - /** - * Check if a root block has already been defined. - * - * @return bool True if block is a root block, false otherwise. - */ - public static function has_children_of_interactive_block() { - return isset( self::$children_of_interactive_block ); + return md5( serialize( $block ) ) === self::$children_of_interactive_block; } - - /** * Find the matching closing tag for an opening tag. * diff --git a/lib/experimental/interactivity-api/directive-processing.php b/lib/experimental/interactivity-api/directive-processing.php index b50b0dda3b0a5..2850840c4f9e5 100644 --- a/lib/experimental/interactivity-api/directive-processing.php +++ b/lib/experimental/interactivity-api/directive-processing.php @@ -104,7 +104,17 @@ function gutenberg_mark_block_interactivity( $block_content, $block, $block_inst } elseif ( WP_Directive_Processor::is_marked_as_children_of_interactive_block( $block ) ) { // Mark children of interactive blocks that are not interactive themselves // to so we can skip them later. - WP_Directive_Processor::unmark_children_of_interactive_block( $block ); + WP_Directive_Processor::unmark_children_of_interactive_block(); + + /** + * Debugging purposes only. It seems that comments are being stripped. + */ + return sprintf( + '
%s
', + // '%s', + // $block['blockName'], + $block_content + ); return get_comment_delimited_block_content( 'core/interactivity-wrapper', array( @@ -113,15 +123,6 @@ function gutenberg_mark_block_interactivity( $block_content, $block, $block_inst ), $block_content ); - /** - * Debugging purposes only. - */ - return sprintf( - '
%s
', - // '%s', - // $block['blockName'], - $block_content - ); } From 4116193d2195135e316115dcdfc6387e7b4edc70 Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Sat, 18 Nov 2023 15:53:11 +0100 Subject: [PATCH 05/27] Use hidden textarea to save comments in production html --- .../directive-processing.php | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/experimental/interactivity-api/directive-processing.php b/lib/experimental/interactivity-api/directive-processing.php index 2850840c4f9e5..28d42553f9ca2 100644 --- a/lib/experimental/interactivity-api/directive-processing.php +++ b/lib/experimental/interactivity-api/directive-processing.php @@ -77,7 +77,6 @@ function gutenberg_mark_interactive_block_children( $parsed_block, $source_block } add_filter( 'render_block_data', 'gutenberg_mark_interactive_block_children', 100, 3 ); - /** * Add a marker indicating if the block is interactive or not. * core/interactivity-wrapper if it is interactive. @@ -107,23 +106,22 @@ function gutenberg_mark_block_interactivity( $block_content, $block, $block_inst WP_Directive_Processor::unmark_children_of_interactive_block(); /** - * Debugging purposes only. It seems that comments are being stripped. + * Debugging purposes only. Nested comments are not allowed. + * We wrap a hidden textarea to save the block content delimited + * by comments so we can later process it. */ return sprintf( - '
%s
', - // '%s', - // $block['blockName'], - $block_content - ); - return get_comment_delimited_block_content( - 'core/interactivity-wrapper', - array( - 'blockName' => $block['blockName'], + ' %2s', + get_comment_delimited_block_content( + 'core/non-interactivity-wrapper', + array( + 'blockName' => $block['blockName'], // We can put extra information about the block here. + ), + $block_content ), $block_content ); - } return $block_content; From 585e8fd023f7a30ca2843a22f3dbea8e7224b1d8 Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Sat, 18 Nov 2023 17:20:55 +0100 Subject: [PATCH 06/27] Use divs as delimiters, comments not working for interactive innner components --- .../directive-processing.php | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/lib/experimental/interactivity-api/directive-processing.php b/lib/experimental/interactivity-api/directive-processing.php index 28d42553f9ca2..c79420c4c5a20 100644 --- a/lib/experimental/interactivity-api/directive-processing.php +++ b/lib/experimental/interactivity-api/directive-processing.php @@ -92,12 +92,13 @@ function gutenberg_mark_block_interactivity( $block_content, $block, $block_inst $block_instance->block_type->supports['interactivity'] ) { // Mark interactive blocks so we can process them later. - return get_comment_delimited_block_content( - 'core/interactivity-wrapper', - array( - 'blockName' => $block['blockName'], - // We can put extra information about the block here. - ), + /** + * Debugging purposes only. Nested comments are not allowed. + * We wrap a hidden textarea to save the block content delimited + * by comments so we can later process it. + */ + return sprintf( + '
%s
', $block_content ); } elseif ( WP_Directive_Processor::is_marked_as_children_of_interactive_block( $block ) ) { @@ -111,15 +112,7 @@ function gutenberg_mark_block_interactivity( $block_content, $block, $block_inst * by comments so we can later process it. */ return sprintf( - ' %2s', - get_comment_delimited_block_content( - 'core/non-interactivity-wrapper', - array( - 'blockName' => $block['blockName'], - // We can put extra information about the block here. - ), - $block_content - ), + '
%s
', $block_content ); } From ca33458b9c8a5faa27381a9431b838b6e62b1c2c Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Tue, 28 Nov 2023 19:02:37 +0100 Subject: [PATCH 07/27] Back to array for references and comment delimiters --- .../class-wp-directive-processor.php | 31 ++++++------ .../directive-processing.php | 47 ++++++++----------- 2 files changed, 36 insertions(+), 42 deletions(-) diff --git a/lib/experimental/interactivity-api/class-wp-directive-processor.php b/lib/experimental/interactivity-api/class-wp-directive-processor.php index 31037f1981a89..1fec096891ba5 100644 --- a/lib/experimental/interactivity-api/class-wp-directive-processor.php +++ b/lib/experimental/interactivity-api/class-wp-directive-processor.php @@ -70,30 +70,31 @@ public static function has_root_block() { } /** - * A string containing the main children of interactive. + * An array containing the main children of interactive. * - * @var string + * @var array + */ + public static $children_of_interactive_block = array(); + + /** + * Add a root block to the variable. + * + * @param array $block The block to add. + * + * @return void */ - public static $children_of_interactive_block = null; - - /** - * Add a root block to the variable. - * - * @param array $block The block to add. - * - * @return void - */ public static function mark_children_of_interactive_block( $block ) { - self::$children_of_interactive_block = md5( serialize( $block ) ); + self::$children_of_interactive_block[] = md5( serialize( $block ) ); } /** * Remove a root block to the variable. * + * @param array $block The block to remove. * @return void */ - public static function unmark_children_of_interactive_block() { - self::$children_of_interactive_block = null; + public static function unmark_children_of_interactive_block( $block ) { + self::$children_of_interactive_block = array_diff( self::$children_of_interactive_block, array( md5( serialize( $block ) ) ) ); } /** @@ -104,7 +105,7 @@ public static function unmark_children_of_interactive_block() { * @return bool True if block is a root block, false otherwise. */ public static function is_marked_as_children_of_interactive_block( $block ) { - return md5( serialize( $block ) ) === self::$children_of_interactive_block; + return in_array( md5( serialize( $block ) ), self::$children_of_interactive_block, true ); } /** diff --git a/lib/experimental/interactivity-api/directive-processing.php b/lib/experimental/interactivity-api/directive-processing.php index c79420c4c5a20..a85f03999a42d 100644 --- a/lib/experimental/interactivity-api/directive-processing.php +++ b/lib/experimental/interactivity-api/directive-processing.php @@ -7,8 +7,6 @@ * @subpackage Interactivity API */ -global $children_of_interactive_block; -$children_of_interactive_block = array(); /** * Mark if the block is a root block. Checks that there is already a root block * in order not to mark template-parts or synced patterns as root blocks, where @@ -88,36 +86,32 @@ function gutenberg_mark_interactive_block_children( $parsed_block, $source_block */ function gutenberg_mark_block_interactivity( $block_content, $block, $block_instance ) { if ( - isset( $block_instance->block_type->supports['interactivity'] ) && - $block_instance->block_type->supports['interactivity'] - ) { + isset( $block_instance->block_type->supports['interactivity'] ) && + $block_instance->block_type->supports['interactivity'] + ) { // Mark interactive blocks so we can process them later. - /** - * Debugging purposes only. Nested comments are not allowed. - * We wrap a hidden textarea to save the block content delimited - * by comments so we can later process it. - */ - return sprintf( - '
%s
', + return get_comment_delimited_block_content( + 'core/interactivity-wrapper', + array( + 'blockName' => $block['blockName'], + // We can put extra information about the block here. + ), $block_content ); } elseif ( WP_Directive_Processor::is_marked_as_children_of_interactive_block( $block ) ) { + WP_Directive_Processor::unmark_children_of_interactive_block( $block ); // Mark children of interactive blocks that are not interactive themselves // to so we can skip them later. - WP_Directive_Processor::unmark_children_of_interactive_block(); - - /** - * Debugging purposes only. Nested comments are not allowed. - * We wrap a hidden textarea to save the block content delimited - * by comments so we can later process it. - */ - return sprintf( - '
%s
', + return get_comment_delimited_block_content( + 'core/non-interactivity-wrapper', + array( + 'blockName' => $block['blockName'], + // We can put extra information about the block here. + ), $block_content ); } - - return $block_content; + return $block_content; } add_filter( 'render_block', 'gutenberg_mark_block_interactivity', 10, 3 ); @@ -141,10 +135,9 @@ function gutenberg_interactivity_evaluate_reference( $path, array $context = arr * passed context) using the subsequent path should be negated. */ $should_negate_value = '!' === $path[0]; - - $path = $should_negate_value ? substr( $path, 1 ) : $path; - $path_segments = explode( '.', $path ); - $current = $store; + $path = $should_negate_value ? substr( $path, 1 ) : $path; + $path_segments = explode( '.', $path ); + $current = $store; foreach ( $path_segments as $p ) { if ( isset( $current[ $p ] ) ) { $current = $current[ $p ]; From 0c4d2e25fceac05ccf6746d4aef8d4b1a0478eac Mon Sep 17 00:00:00 2001 From: David Arenas Date: Wed, 29 Nov 2023 18:24:29 +0100 Subject: [PATCH 08/27] Restore changes from `store()` migration PR --- .../class-wp-interactivity-initial-state.php | 85 ++++++++ .../class-wp-interactivity-store.php | 69 ------- .../directive-processing.php | 2 +- .../interactivity-api/initial-state.php | 29 +++ lib/experimental/interactivity-api/store.php | 28 --- lib/load.php | 4 +- ...ss-wp-interactivity-initial-state-test.php | 111 +++++++++++ .../class-wp-interactivity-store-test.php | 186 ------------------ 8 files changed, 228 insertions(+), 286 deletions(-) create mode 100644 lib/experimental/interactivity-api/class-wp-interactivity-initial-state.php delete mode 100644 lib/experimental/interactivity-api/class-wp-interactivity-store.php create mode 100644 lib/experimental/interactivity-api/initial-state.php delete mode 100644 lib/experimental/interactivity-api/store.php create mode 100644 phpunit/experimental/interactivity-api/class-wp-interactivity-initial-state-test.php delete mode 100644 phpunit/experimental/interactivity-api/class-wp-interactivity-store-test.php diff --git a/lib/experimental/interactivity-api/class-wp-interactivity-initial-state.php b/lib/experimental/interactivity-api/class-wp-interactivity-initial-state.php new file mode 100644 index 0000000000000..a1edbcff776fb --- /dev/null +++ b/lib/experimental/interactivity-api/class-wp-interactivity-initial-state.php @@ -0,0 +1,85 @@ +%s', + wp_json_encode( self::$initial_state, JSON_HEX_TAG | JSON_HEX_AMP ) + ); + } +} diff --git a/lib/experimental/interactivity-api/class-wp-interactivity-store.php b/lib/experimental/interactivity-api/class-wp-interactivity-store.php deleted file mode 100644 index c53701b14e8af..0000000000000 --- a/lib/experimental/interactivity-api/class-wp-interactivity-store.php +++ /dev/null @@ -1,69 +0,0 @@ -%s', - wp_json_encode( self::$store, JSON_HEX_TAG | JSON_HEX_AMP ) - ); - } -} diff --git a/lib/experimental/interactivity-api/directive-processing.php b/lib/experimental/interactivity-api/directive-processing.php index 064fc8ea62cbb..a2f00d624bd20 100644 --- a/lib/experimental/interactivity-api/directive-processing.php +++ b/lib/experimental/interactivity-api/directive-processing.php @@ -66,7 +66,7 @@ function gutenberg_process_directives_in_root_blocks( $block_content, $block ) { */ function gutenberg_interactivity_evaluate_reference( $path, array $context = array() ) { $store = array_merge( - WP_Interactivity_Store::get_data(), + WP_Interactivity_Initial_State::get_state(), array( 'context' => $context ) ); diff --git a/lib/experimental/interactivity-api/initial-state.php b/lib/experimental/interactivity-api/initial-state.php new file mode 100644 index 0000000000000..a38d0da631f3c --- /dev/null +++ b/lib/experimental/interactivity-api/initial-state.php @@ -0,0 +1,29 @@ +assertEmpty( WP_Interactivity_Initial_State::get_data() ); + } + + public function test_initial_state_can_be_merged() { + $state = array( + 'a' => 1, + 'b' => 2, + 'nested' => array( + 'c' => 3, + ), + ); + WP_Interactivity_Initial_State::merge_state( 'core', $state ); + $this->assertSame( $state, WP_Interactivity_Initial_State::get_state( 'core' ) ); + } + + public function test_initial_state_can_be_extended() { + WP_Interactivity_Initial_State::merge_state( 'core', array( 'a' => 1 ) ); + WP_Interactivity_Initial_State::merge_state( 'core', array( 'b' => 2 ) ); + WP_Interactivity_Initial_State::merge_state( 'custom', array( 'c' => 3 ) ); + $this->assertSame( + array( + 'core' => array( + 'a' => 1, + 'b' => 2, + ), + 'custom' => array( + 'c' => 3, + ), + ), + WP_Interactivity_Initial_State::get_data() + ); + } + + public function test_initial_state_existing_props_should_be_overwritten() { + WP_Interactivity_Initial_State::merge_state( 'core', array( 'a' => 1 ) ); + WP_Interactivity_Initial_State::merge_state( 'core', array( 'a' => 'overwritten' ) ); + $this->assertSame( + array( + 'core' => array( + 'a' => 'overwritten', + ), + ), + WP_Interactivity_Initial_State::get_data() + ); + } + + public function test_initial_state_existing_indexed_arrays_should_be_replaced() { + WP_Interactivity_Initial_State::merge_state( 'core', array( 'a' => array( 1, 2 ) ) ); + WP_Interactivity_Initial_State::merge_state( 'core', array( 'a' => array( 3, 4 ) ) ); + $this->assertSame( + array( + 'core' => array( + 'a' => array( 3, 4 ), + ), + ), + WP_Interactivity_Initial_State::get_data() + ); + } + + public function test_initial_state_should_be_correctly_rendered() { + WP_Interactivity_Initial_State::merge_state( 'core', array( 'a' => 1 ) ); + WP_Interactivity_Initial_State::merge_state( 'core', array( 'b' => 2 ) ); + WP_Interactivity_Initial_State::merge_state( 'custom', array( 'c' => 3 ) ); + + ob_start(); + WP_Interactivity_Initial_State::render(); + $rendered = ob_get_clean(); + $this->assertSame( + '', + $rendered + ); + } + + public function test_initial_state_should_also_escape_tags_and_amps() { + WP_Interactivity_Initial_State::merge_state( + 'test', + array( + 'amps' => 'http://site.test/?foo=1&baz=2&bar=3', + 'tags' => 'Do not do this: