WP_Interactivity_API::process_directives_args( string $html, array $context_stack, array $namespace_stack ): string|null

This function’s access is marked private. This means it is not intended for use by plugin or theme developers, only in other core functions. It is listed here for completeness.

Processes the interactivity directives contained within the HTML content and updates the markup accordingly.

Description

It needs the context and namespace stacks to be passed by reference, and it returns null if the HTML contains unbalanced tags.

Parameters

$htmlstringrequired
The HTML content to process.
$context_stackarrayrequired
The reference to the array used to keep track of contexts during processing.
$namespace_stackarrayrequired
The reference to the array used to manage namespaces during processing.

Return

string|null The processed HTML content. It returns null when the HTML contains unbalanced tags.

Source

private function process_directives_args( string $html, array &$context_stack, array &$namespace_stack ) {
	$p          = new WP_Interactivity_API_Directives_Processor( $html );
	$tag_stack  = array();
	$unbalanced = false;

	$directive_processor_prefixes          = array_keys( self::$directive_processors );
	$directive_processor_prefixes_reversed = array_reverse( $directive_processor_prefixes );

	while ( $p->next_tag( array( 'tag_closers' => 'visit' ) ) ) {
		$tag_name = $p->get_tag();

		/*
		 * Directives inside SVG and MATH tags are not processed,
		 * as they are not compatible with the Tag Processor yet.
		 * We still process the rest of the HTML.
		 */
		if ( 'SVG' === $tag_name || 'MATH' === $tag_name ) {
			$p->skip_to_tag_closer();
			continue;
		}

		if ( $p->is_tag_closer() ) {
			list( $opening_tag_name, $directives_prefixes ) = end( $tag_stack );

			if ( 0 === count( $tag_stack ) || $opening_tag_name !== $tag_name ) {

				/*
				 * If the tag stack is empty or the matching opening tag is not the
				 * same than the closing tag, it means the HTML is unbalanced and it
				 * stops processing it.
				 */
				$unbalanced = true;
				break;
			} else {
				// Remove the last tag from the stack.
				array_pop( $tag_stack );
			}
		} else {
			if ( 0 !== count( $p->get_attribute_names_with_prefix( 'data-wp-each-child' ) ) ) {
				/*
				 * If the tag has a `data-wp-each-child` directive, jump to its closer
				 * tag because those tags have already been processed.
				 */
				$p->next_balanced_tag_closer_tag();
				continue;
			} else {
				$directives_prefixes = array();

				// Checks if there is a server directive processor registered for each directive.
				foreach ( $p->get_attribute_names_with_prefix( 'data-wp-' ) as $attribute_name ) {
					list( $directive_prefix ) = $this->extract_prefix_and_suffix( $attribute_name );
					if ( array_key_exists( $directive_prefix, self::$directive_processors ) ) {
						$directives_prefixes[] = $directive_prefix;
					}
				}

				/*
				 * If this tag will visit its closer tag, it adds it to the tag stack
				 * so it can process its closing tag and check for unbalanced tags.
				 */
				if ( $p->has_and_visits_its_closer_tag() ) {
					$tag_stack[] = array( $tag_name, $directives_prefixes );
				}
			}
		}
		/*
		 * If the matching opener tag didn't have any directives, it can skip the
		 * processing.
		 */
		if ( 0 === count( $directives_prefixes ) ) {
			continue;
		}

		// Directive processing might be different depending on if it is entering the tag or exiting it.
		$modes = array(
			'enter' => ! $p->is_tag_closer(),
			'exit'  => $p->is_tag_closer() || ! $p->has_and_visits_its_closer_tag(),
		);

		foreach ( $modes as $mode => $should_run ) {
			if ( ! $should_run ) {
				continue;
			}

			/*
			 * Sorts the attributes by the order of the `directives_processor` array
			 * and checks what directives are present in this element.
			 */
			$existing_directives_prefixes = array_intersect(
				'enter' === $mode ? $directive_processor_prefixes : $directive_processor_prefixes_reversed,
				$directives_prefixes
			);
			foreach ( $existing_directives_prefixes as $directive_prefix ) {
				$func = is_array( self::$directive_processors[ $directive_prefix ] )
					? self::$directive_processors[ $directive_prefix ]
					: array( $this, self::$directive_processors[ $directive_prefix ] );

				call_user_func_array(
					$func,
					array( $p, $mode, &$context_stack, &$namespace_stack, &$tag_stack )
				);
			}
		}
	}

	/*
	 * It returns null if the HTML is unbalanced because unbalanced HTML is
	 * not safe to process. In that case, the Interactivity API runtime will
	 * update the HTML on the client side during the hydration.
	 */
	return $unbalanced || 0 < count( $tag_stack ) ? null : $p->get_updated_html();
}

Changelog

VersionDescription
6.5.0Introduced.

User Contributed Notes

You must log in before being able to contribute a note or feedback.