WP_HTML_Processor::steppublicWP 6.4.0

Steps through the HTML document and stop at the next tag, if any.

Method of the class: WP_HTML_Processor{}

No Hooks.

Returns

true|false. Whether a tag was matched.

Usage

$WP_HTML_Processor = new WP_HTML_Processor();
$WP_HTML_Processor->step( $node_to_process ): bool;
$node_to_process(string)
Whether to parse the next node or reprocess the current node.
Default: self::PROCESS_NEXT_NODE

Notes

  • See: self::PROCESS_NEXT_NODE
  • See: self::REPROCESS_CURRENT_NODE

Changelog

Since 6.4.0 Introduced.

WP_HTML_Processor::step() code WP 6.9

public function step( $node_to_process = self::PROCESS_NEXT_NODE ): bool {
	// Refuse to proceed if there was a previous error.
	if ( null !== $this->last_error ) {
		return false;
	}

	if ( self::REPROCESS_CURRENT_NODE !== $node_to_process ) {
		/*
		 * Void elements still hop onto the stack of open elements even though
		 * there's no corresponding closing tag. This is important for managing
		 * stack-based operations such as "navigate to parent node" or checking
		 * on an element's breadcrumbs.
		 *
		 * When moving on to the next node, therefore, if the bottom-most element
		 * on the stack is a void element, it must be closed.
		 */
		$top_node = $this->state->stack_of_open_elements->current_node();
		if ( isset( $top_node ) && ! $this->expects_closer( $top_node ) ) {
			$this->state->stack_of_open_elements->pop();
		}
	}

	if ( self::PROCESS_NEXT_NODE === $node_to_process ) {
		parent::next_token();
		if ( WP_HTML_Tag_Processor::STATE_TEXT_NODE === $this->parser_state ) {
			parent::subdivide_text_appropriately();
		}
	}

	// Finish stepping when there are no more tokens in the document.
	if (
		WP_HTML_Tag_Processor::STATE_INCOMPLETE_INPUT === $this->parser_state ||
		WP_HTML_Tag_Processor::STATE_COMPLETE === $this->parser_state
	) {
		return false;
	}

	$adjusted_current_node = $this->get_adjusted_current_node();
	$is_closer             = $this->is_tag_closer();
	$is_start_tag          = WP_HTML_Tag_Processor::STATE_MATCHED_TAG === $this->parser_state && ! $is_closer;
	$token_name            = $this->get_token_name();

	if ( self::REPROCESS_CURRENT_NODE !== $node_to_process ) {
		$this->state->current_token = new WP_HTML_Token(
			$this->bookmark_token(),
			$token_name,
			$this->has_self_closing_flag(),
			$this->release_internal_bookmark_on_destruct
		);
	}

	$parse_in_current_insertion_mode = (
		0 === $this->state->stack_of_open_elements->count() ||
		'html' === $adjusted_current_node->namespace ||
		(
			'math' === $adjusted_current_node->integration_node_type &&
			(
				( $is_start_tag && ! in_array( $token_name, array( 'MGLYPH', 'MALIGNMARK' ), true ) ) ||
				'#text' === $token_name
			)
		) ||
		(
			'math' === $adjusted_current_node->namespace &&
			'ANNOTATION-XML' === $adjusted_current_node->node_name &&
			$is_start_tag && 'SVG' === $token_name
		) ||
		(
			'html' === $adjusted_current_node->integration_node_type &&
			( $is_start_tag || '#text' === $token_name )
		)
	);

	try {
		if ( ! $parse_in_current_insertion_mode ) {
			return $this->step_in_foreign_content();
		}

		switch ( $this->state->insertion_mode ) {
			case WP_HTML_Processor_State::INSERTION_MODE_INITIAL:
				return $this->step_initial();

			case WP_HTML_Processor_State::INSERTION_MODE_BEFORE_HTML:
				return $this->step_before_html();

			case WP_HTML_Processor_State::INSERTION_MODE_BEFORE_HEAD:
				return $this->step_before_head();

			case WP_HTML_Processor_State::INSERTION_MODE_IN_HEAD:
				return $this->step_in_head();

			case WP_HTML_Processor_State::INSERTION_MODE_IN_HEAD_NOSCRIPT:
				return $this->step_in_head_noscript();

			case WP_HTML_Processor_State::INSERTION_MODE_AFTER_HEAD:
				return $this->step_after_head();

			case WP_HTML_Processor_State::INSERTION_MODE_IN_BODY:
				return $this->step_in_body();

			case WP_HTML_Processor_State::INSERTION_MODE_IN_TABLE:
				return $this->step_in_table();

			case WP_HTML_Processor_State::INSERTION_MODE_IN_TABLE_TEXT:
				return $this->step_in_table_text();

			case WP_HTML_Processor_State::INSERTION_MODE_IN_CAPTION:
				return $this->step_in_caption();

			case WP_HTML_Processor_State::INSERTION_MODE_IN_COLUMN_GROUP:
				return $this->step_in_column_group();

			case WP_HTML_Processor_State::INSERTION_MODE_IN_TABLE_BODY:
				return $this->step_in_table_body();

			case WP_HTML_Processor_State::INSERTION_MODE_IN_ROW:
				return $this->step_in_row();

			case WP_HTML_Processor_State::INSERTION_MODE_IN_CELL:
				return $this->step_in_cell();

			case WP_HTML_Processor_State::INSERTION_MODE_IN_SELECT:
				return $this->step_in_select();

			case WP_HTML_Processor_State::INSERTION_MODE_IN_SELECT_IN_TABLE:
				return $this->step_in_select_in_table();

			case WP_HTML_Processor_State::INSERTION_MODE_IN_TEMPLATE:
				return $this->step_in_template();

			case WP_HTML_Processor_State::INSERTION_MODE_AFTER_BODY:
				return $this->step_after_body();

			case WP_HTML_Processor_State::INSERTION_MODE_IN_FRAMESET:
				return $this->step_in_frameset();

			case WP_HTML_Processor_State::INSERTION_MODE_AFTER_FRAMESET:
				return $this->step_after_frameset();

			case WP_HTML_Processor_State::INSERTION_MODE_AFTER_AFTER_BODY:
				return $this->step_after_after_body();

			case WP_HTML_Processor_State::INSERTION_MODE_AFTER_AFTER_FRAMESET:
				return $this->step_after_after_frameset();

			// This should be unreachable but PHP doesn't have total type checking on switch.
			default:
				$this->bail( "Unaware of the requested parsing mode: '{$this->state->insertion_mode}'." );
		}
	} catch ( WP_HTML_Unsupported_Exception $e ) {
		/*
		 * Exceptions are used in this class to escape deep call stacks that
		 * otherwise might involve messier calling and return conventions.
		 */
		return false;
	}
}