WP_HTML_Tag_Processor::apply_attributes_updates()privateWP 6.2.0

Applies attribute updates to HTML document.

Method of the class: WP_HTML_Tag_Processor{}

No Hooks.

Return

Int. How many bytes the given pointer moved in response to the updates.

Usage

// private - for code of main (parent) class only
$result = $this->apply_attributes_updates( $shift_this_point ): int;
$shift_this_point(int) (required)
Accumulate and return shift for this position.

Changelog

Since 6.2.0 Introduced.
Since 6.2.1 Accumulates shift for internal cursor and passed pointer.
Since 6.3.0 Invalidate any bookmarks whose targets are overwritten.

WP_HTML_Tag_Processor::apply_attributes_updates() code WP 6.7.1

private function apply_attributes_updates( int $shift_this_point ): int {
	if ( ! count( $this->lexical_updates ) ) {
		return 0;
	}

	$accumulated_shift_for_given_point = 0;

	/*
	 * Attribute updates can be enqueued in any order but updates
	 * to the document must occur in lexical order; that is, each
	 * replacement must be made before all others which follow it
	 * at later string indices in the input document.
	 *
	 * Sorting avoid making out-of-order replacements which
	 * can lead to mangled output, partially-duplicated
	 * attributes, and overwritten attributes.
	 */
	usort( $this->lexical_updates, array( self::class, 'sort_start_ascending' ) );

	$bytes_already_copied = 0;
	$output_buffer        = '';
	foreach ( $this->lexical_updates as $diff ) {
		$shift = strlen( $diff->text ) - $diff->length;

		// Adjust the cursor position by however much an update affects it.
		if ( $diff->start < $this->bytes_already_parsed ) {
			$this->bytes_already_parsed += $shift;
		}

		// Accumulate shift of the given pointer within this function call.
		if ( $diff->start < $shift_this_point ) {
			$accumulated_shift_for_given_point += $shift;
		}

		$output_buffer       .= substr( $this->html, $bytes_already_copied, $diff->start - $bytes_already_copied );
		$output_buffer       .= $diff->text;
		$bytes_already_copied = $diff->start + $diff->length;
	}

	$this->html = $output_buffer . substr( $this->html, $bytes_already_copied );

	/*
	 * Adjust bookmark locations to account for how the text
	 * replacements adjust offsets in the input document.
	 */
	foreach ( $this->bookmarks as $bookmark_name => $bookmark ) {
		$bookmark_end = $bookmark->start + $bookmark->length;

		/*
		 * Each lexical update which appears before the bookmark's endpoints
		 * might shift the offsets for those endpoints. Loop through each change
		 * and accumulate the total shift for each bookmark, then apply that
		 * shift after tallying the full delta.
		 */
		$head_delta = 0;
		$tail_delta = 0;

		foreach ( $this->lexical_updates as $diff ) {
			$diff_end = $diff->start + $diff->length;

			if ( $bookmark->start < $diff->start && $bookmark_end < $diff->start ) {
				break;
			}

			if ( $bookmark->start >= $diff->start && $bookmark_end < $diff_end ) {
				$this->release_bookmark( $bookmark_name );
				continue 2;
			}

			$delta = strlen( $diff->text ) - $diff->length;

			if ( $bookmark->start >= $diff->start ) {
				$head_delta += $delta;
			}

			if ( $bookmark_end >= $diff_end ) {
				$tail_delta += $delta;
			}
		}

		$bookmark->start  += $head_delta;
		$bookmark->length += $tail_delta - $head_delta;
	}

	$this->lexical_updates = array();

	return $accumulated_shift_for_given_point;
}