WP_HTML_Tag_Processor::next_tag( array|string|null $query = null ): bool

Finds the next tag matching the $query.


Parameters

$query array|string|null Optional
Which tag name to find, having which class, etc. Default is to find any tag.
  • tag_name string|null
    Which tag to find, or null for "any tag."
  • match_offset int|null
    Find the Nth tag matching all search criteria.
    1 for "first" tag, 3 for "third," etc.
    Defaults to first tag.
  • class_name string|null
    Tag must contain this whole class name to match.
  • tag_closers string|null
    "visit" or "skip": whether to stop on tag closers, e.g. </div>.

Default: null


Top ↑

Return

bool Whether a tag was matched.


Top ↑

Source

File: wp-includes/html-api/class-wp-html-tag-processor.php. View all references

public function next_tag( $query = null ) {
	$this->parse_query( $query );
	$already_found = 0;

	do {
		if ( $this->bytes_already_parsed >= strlen( $this->html ) ) {
			return false;
		}

		// Find the next tag if it exists.
		if ( false === $this->parse_next_tag() ) {
			$this->bytes_already_parsed = strlen( $this->html );

			return false;
		}

		// Parse all of its attributes.
		while ( $this->parse_next_attribute() ) {
			continue;
		}

		// Ensure that the tag closes before the end of the document.
		if ( $this->bytes_already_parsed >= strlen( $this->html ) ) {
			return false;
		}

		$tag_ends_at = strpos( $this->html, '>', $this->bytes_already_parsed );
		if ( false === $tag_ends_at ) {
			return false;
		}
		$this->tag_ends_at          = $tag_ends_at;
		$this->bytes_already_parsed = $tag_ends_at;

		// Finally, check if the parsed tag and its attributes match the search query.
		if ( $this->matches() ) {
			++$already_found;
		}

		/*
		 * For non-DATA sections which might contain text that looks like HTML tags but
		 * isn't, scan with the appropriate alternative mode. Looking at the first letter
		 * of the tag name as a pre-check avoids a string allocation when it's not needed.
		 */
		$t = $this->html[ $this->tag_name_starts_at ];
		if (
			! $this->is_closing_tag &&
			(
				'i' === $t || 'I' === $t ||
				'n' === $t || 'N' === $t ||
				's' === $t || 'S' === $t ||
				't' === $t || 'T' === $t
			) ) {
			$tag_name = $this->get_tag();

			if ( 'SCRIPT' === $tag_name && ! $this->skip_script_data() ) {
				$this->bytes_already_parsed = strlen( $this->html );
				return false;
			} elseif (
				( 'TEXTAREA' === $tag_name || 'TITLE' === $tag_name ) &&
				! $this->skip_rcdata( $tag_name )
			) {
				$this->bytes_already_parsed = strlen( $this->html );
				return false;
			} elseif (
				(
					'IFRAME' === $tag_name ||
					'NOEMBED' === $tag_name ||
					'NOFRAMES' === $tag_name ||
					'NOSCRIPT' === $tag_name ||
					'STYLE' === $tag_name
				) &&
				! $this->skip_rawtext( $tag_name )
			) {
				/*
				 * "XMP" should be here too but its rules are more complicated and require the
				 * complexity of the HTML Processor (it needs to close out any open P element,
				 * meaning it can't be skipped here or else the HTML Processor will lose its
				 * place). For now, it can be ignored as it's a rare HTML tag in practice and
				 * any normative HTML should be using PRE instead.
				 */
				$this->bytes_already_parsed = strlen( $this->html );
				return false;
			}
		}
	} while ( $already_found < $this->sought_match_offset );

	return true;
}


Top ↑

Changelog

Changelog
Version Description
6.2.0 Introduced.

Top ↑

User Contributed Notes

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