WP_Interactivity_API
Main class for server-side Interactivity API processing.
Source: wp-includes/interactivity-api/class-wp-interactivity-api.php
Since: 6.5.0
final class WP_Interactivity_API
Properties
$directive_processors
private static array $directive_processors
Maps directive attribute names to their processor methods.
Value:
array(
'data-wp-interactive' => 'data_wp_interactive_processor',
'data-wp-router-region' => 'data_wp_router_region_processor',
'data-wp-context' => 'data_wp_context_processor',
'data-wp-bind' => 'data_wp_bind_processor',
'data-wp-class' => 'data_wp_class_processor',
'data-wp-style' => 'data_wp_style_processor',
'data-wp-text' => 'data_wp_text_processor',
'data-wp-each' => 'data_wp_each_processor',
)
$state_data
private array $state_data = array()
Initial state for each store namespace. Serialized and sent to client for hydration.
$config_data
private array $config_data = array()
Configuration for each store namespace. Accessible client-side via getConfig().
$derived_state_closures
private array $derived_state_closures = array()
Since: 6.9.0. Tracks derived state closures accessed during SSR for lazy client hydration.
$has_processed_router_region
private bool $has_processed_router_region = false
Whether data-wp-router-region has been processed (triggers loading bar styles).
$script_modules_that_can_load_on_client_navigation
private array $script_modules_that_can_load_on_client_navigation = array()
Since: 6.9.0. Script modules compatible with client-side navigation.
$namespace_stack
private ?array $namespace_stack = null
Since: 6.6.0. Stack of namespaces from data-wp-interactive during processing.
$context_stack
private ?array $context_stack = null
Since: 6.6.0. Stack of contexts from data-wp-context during processing.
$current_element
private ?array $current_element = null
Since: 6.7.0. Array representation of element currently being processed.
Public Methods
state()
Gets and/or sets initial state for a store namespace.
public function state( ?string $store_namespace = null, ?array $state = null ): array
Since: 6.5.0
Since: 6.6.0 — $store_namespace is optional during directive processing.
Parameters:
| Name | Type | Description |
|---|---|---|
$store_namespace |
string|null |
Store namespace identifier |
$state |
array|null |
State to merge |
Returns: array — Current state for namespace.
Behavior:
- If
$store_namespaceis null/empty and$stateis provided →_doing_it_wrong - If
$store_namespaceis omitted during processing → uses current namespace from stack - Merges
$staterecursively with existing state viaarray_replace_recursive()
config()
Gets and/or sets configuration for a store namespace.
public function config( string $store_namespace, array $config = array() ): array
Since: 6.5.0
Parameters:
| Name | Type | Description |
|---|---|---|
$store_namespace |
string |
Store namespace identifier |
$config |
array |
Config to merge |
Returns: array — Current config for namespace.
get_context()
Returns context for a namespace from the context stack.
public function get_context( ?string $store_namespace = null ): array
Since: 6.6.0
Parameters:
| Name | Type | Description |
|---|---|---|
$store_namespace |
string|null |
Namespace. Uses current if omitted. |
Returns: array — Context for namespace, or empty array.
Note: Only valid during process_directives(). Triggers _doing_it_wrong otherwise.
get_element()
Returns array representation of current element being processed.
public function get_element(): ?array
Since: 6.7.0
Returns: array{attributes: array<string, string|bool>}|null
Note: Only valid during process_directives().
add_hooks()
Registers necessary hooks for the Interactivity API.
public function add_hooks(): void
Since: 6.5.0
Since: 6.9.0 — Adds client-side navigation support.
Hooks Added:
script_module_data_@wordpress/interactivity→filter_script_module_interactivity_data()script_module_data_@wordpress/interactivity-router→filter_script_module_interactivity_router_data()wp_script_attributes→add_load_on_client_navigation_attribute_to_script_modules()
filter_script_module_interactivity_data()
Filters script module data for @wordpress/interactivity.
public function filter_script_module_interactivity_data( array $data ): array
Since: 6.7.0
Since: 6.9.0 — Serializes derived state props.
Parameters:
| Name | Type | Description |
|---|---|---|
$data |
array |
Existing data |
Returns: array — Data with state, config, and derivedStateClosures added.
filter_script_module_interactivity_router_data()
Filters script module data for @wordpress/interactivity-router.
public function filter_script_module_interactivity_router_data( array $data ): array
Since: 6.7.0
Returns: array — Data with i18n strings for loading/loaded messages.
add_load_on_client_navigation_attribute_to_script_modules()
Adds data-wp-router-options attribute to compatible script modules.
public function add_load_on_client_navigation_attribute_to_script_modules( $attributes ): array
Since: 6.9.0
Parameters:
| Name | Type | Description |
|---|---|---|
$attributes |
array |
Script tag attributes |
Returns: array — Modified attributes with data-wp-router-options JSON.
add_client_navigation_support_to_script_module()
Marks a script module as compatible with client-side navigation.
public function add_client_navigation_support_to_script_module( string $script_module_id ): void
Since: 6.9.0
Parameters:
| Name | Type | Description |
|---|---|---|
$script_module_id |
string |
The script module identifier |
process_directives()
Processes interactivity directives in HTML content.
public function process_directives( string $html ): string
Since: 6.5.0
Parameters:
| Name | Type | Description |
|---|---|---|
$html |
string |
HTML content to process |
Returns: string — Processed HTML, or original if unbalanced tags.
Behavior:
- Early return if no
data-wp-found - Initializes namespace and context stacks
- Calls
_process_directives()for actual work - Cleans up stacks
- Returns original HTML if processing returned null (unbalanced)
print_router_markup()
Outputs loading bar markup for the interactivity router.
public function print_router_markup(): void
Since: 6.7.0
Output:
<div
class="wp-interactivity-router-loading-bar"
data-wp-interactive="core/router"
data-wp-class--start-animation="state.navigation.hasStarted"
data-wp-class--finish-animation="state.navigation.hasFinished"
></div>
Deprecated Methods
print_client_interactivity_data()
public function print_client_interactivity_data(): void
Deprecated: 6.7.0. Use script_module_data_{$module_id} filter instead.
register_script_modules()
public function register_script_modules(): void
Deprecated: 6.7.0. Use wp_default_script_modules() instead.
print_router_loading_and_screen_reader_markup()
public function print_router_loading_and_screen_reader_markup(): void
Deprecated: 6.7.0. Use print_router_markup() instead.
Private Methods
_process_directives()
Internal processing of directives using shared stacks.
private function _process_directives( string $html ): ?string
Since: 6.6.0
Returns: string|null — Processed HTML or null if unbalanced.
Processing Order:
- Create
WP_Interactivity_API_Directives_Processor - Skip SVG and MATH tags (incompatible with Tag Processor)
- Track balanced tags via stack
- For each tag with directives, run processors in order
- On exit, run processors in reverse order
- Return null if unbalanced tags detected
evaluate()
Evaluates a directive reference path against state/context.
private function evaluate( array $entry ): mixed
Since: 6.5.0
Since: 6.6.0 — Supports derived state.
Since: 6.9.0 — Receives $entry array instead of string.
Parameters:
| Name | Type | Description |
|---|---|---|
$entry |
array |
Directive entry with namespace, value, suffix, unique_id |
Returns: mixed|null — Evaluated value, negated if prefixed with !.
Special Cases:
!path→ Returns negated value.lengthon arrays/strings → Returns count/strlen (since 6.8.0)- Closures → Executed with namespace pushed to stack, tracked for hydration
parse_directive_name()
Parses directive attribute name into components.
private function parse_directive_name( string $directive_name ): ?array
Since: 6.9.0
Returns:
array(
'prefix' => string, // Main directive name without "data-wp-"
'suffix' => ?string, // After first "--"
'unique_id' => ?string, // After "---"
)
Examples:
data-wp-bind--src→['prefix' => 'bind', 'suffix' => 'src', 'unique_id' => null]data-wp-class--active---123→['prefix' => 'class', 'suffix' => 'active', 'unique_id' => '123']
extract_directive_value()
Extracts namespace and value from directive attribute.
private function extract_directive_value( $directive_value, $default_namespace = null ): array
Since: 6.5.0
Returns: array — [namespace, value]
Examples:
'state.foo'→['defaultNs', 'state.foo']'otherPlugin::state.foo'→['otherPlugin', 'state.foo']'{"isOpen": false}'→['defaultNs', ['isOpen' => false]]
get_directive_entries()
Gets all valid directive entries for a prefix from current element.
private function get_directive_entries( WP_Interactivity_API_Directives_Processor $p, string $prefix ): array
Since: 6.9.0
Returns: array — Sorted array of entries with namespace, value, suffix, unique_id.
kebab_to_camel_case()
Converts kebab-case to camelCase.
private function kebab_to_camel_case( string $str ): string
Since: 6.5.0
Example: 'my-variable-name' → 'myVariableName'
merge_style_property()
Merges a style property into a style attribute string.
private function merge_style_property( string $style_attribute_value, string $style_property_name, $style_property_value ): string
Since: 6.5.0
Examples:
merge_style_property('color:green;', 'color', 'red')→'color:red;'merge_style_property('background:green;', 'color', 'red')→'background:green;color:red;'merge_style_property('color:green;', 'color', null)→''
get_router_animation_styles()
Returns CSS for the router loading bar animation.
private function get_router_animation_styles(): string
Since: 6.5.0
Directive Processors
All processors receive:
WP_Interactivity_API_Directives_Processor $p— The processor instancestring $mode—'enter'or'exit'array &$tag_stack— Reference to tag stack (onlydata_wp_each_processor)
data_wp_interactive_processor()
Processes data-wp-interactive directive.
private function data_wp_interactive_processor( WP_Interactivity_API_Directives_Processor $p, string $mode ): void
Since: 6.5.0
Behavior:
enter: Parses namespace from attribute value (string or JSON{"namespace":"..."}) and pushes to stackexit: Pops namespace from stack
data_wp_context_processor()
Processes data-wp-context directive.
private function data_wp_context_processor( WP_Interactivity_API_Directives_Processor $p, string $mode ): void
Since: 6.5.0
Behavior:
enter: Merges context JSON into stack with namespace keyexit: Pops context from stack
data_wp_bind_processor()
Processes data-wp-bind--{attr} directives.
private function data_wp_bind_processor( WP_Interactivity_API_Directives_Processor $p, string $mode ): void
Since: 6.5.0
Behavior:
- Evaluates reference and sets/removes attribute
- Boolean values for
aria-*anddata-*become"true"/"false"strings falseremoves non-aria/data attributes
data_wp_class_processor()
Processes data-wp-class--{classname} directives.
private function data_wp_class_processor( WP_Interactivity_API_Directives_Processor $p, string $mode ): void
Since: 6.5.0
Behavior:
- Truthy value adds class
- Falsy value removes class
- Supports unique IDs:
data-wp-class--active---123→ classactive---123
data_wp_style_processor()
Processes data-wp-style--{property} directives.
private function data_wp_style_processor( WP_Interactivity_API_Directives_Processor $p, string $mode ): void
Since: 6.5.0
Behavior:
- Updates or removes style property in
styleattribute - Removes entire
styleattribute if empty after modification
data_wp_text_processor()
Processes data-wp-text directive.
private function data_wp_text_processor( WP_Interactivity_API_Directives_Processor $p, string $mode ): void
Since: 6.5.0
Behavior:
- Replaces element content with evaluated value (escaped)
- Only processes strings and numbers (per Preact behavior)
- Other types clear the content
data_wp_router_region_processor()
Processes data-wp-router-region directive.
private function data_wp_router_region_processor( WP_Interactivity_API_Directives_Processor $p, string $mode ): void
Since: 6.5.0
Behavior:
- Only runs once per page
- Registers and enqueues
wp-interactivity-router-animationsstyles - Adds
print_router_markup()towp_footer
data_wp_each_processor()
Processes data-wp-each directive on <template> tags.
private function data_wp_each_processor( WP_Interactivity_API_Directives_Processor $p, string $mode, array &$tag_stack ): void
Since: 6.5.0
Since: 6.9.0 — Includes list path in data-wp-each-child.
Behavior:
- Only processes
<template>tags - Evaluates array reference
- Skips if: manual SSR (
data-wp-each-childexists), non-list array, or invalid template content - For each item:
- Creates context with item (name from suffix, default
item) - Recursively processes inner content
- Adds
data-wp-each-childto top-level rendered elements
- Creates context with item (name from suffix, default
- Appends all processed content after template closer
Example:
<template data-wp-each="state.items" data-wp-each-key="context.item.id">
<li data-wp-text="context.item.name"></li>
</template>