WP_HTML_Tag_Processor::apply_attributes_updates( int $shift_this_point ): int

In this article

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

Applies attribute updates to HTML document.

Parameters

$shift_this_pointintrequired
Accumulate and return shift for this position.

Return

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

Source

 *
 * This flag is set upon the first change that requires a string update.
 *
 * @var bool $modified
 */
$modified = false;

$seen      = array();
$to_remove = array();
$is_quirks = self::QUIRKS_MODE === $this->compat_mode;
if ( $is_quirks ) {
	foreach ( $this->classname_updates as $updated_name => $action ) {
		if ( self::REMOVE_CLASS === $action ) {
			$to_remove[] = strtolower( $updated_name );
		}
	}
} else {
	foreach ( $this->classname_updates as $updated_name => $action ) {
		if ( self::REMOVE_CLASS === $action ) {
			$to_remove[] = $updated_name;
		}
	}
}

// Remove unwanted classes by only copying the new ones.
$existing_class_length = strlen( $existing_class );
while ( $at < $existing_class_length ) {
	// Skip to the first non-whitespace character.
	$ws_at     = $at;
	$ws_length = strspn( $existing_class, " \t\f\r\n", $ws_at );
	$at       += $ws_length;

	// Capture the class name – it's everything until the next whitespace.
	$name_length = strcspn( $existing_class, " \t\f\r\n", $at );
	if ( 0 === $name_length ) {
		// If no more class names are found then that's the end.
		break;
	}

	$name                  = substr( $existing_class, $at, $name_length );
	$comparable_class_name = $is_quirks ? strtolower( $name ) : $name;
	$at                   += $name_length;

	// If this class is marked for removal, remove it and move on to the next one.
	if ( in_array( $comparable_class_name, $to_remove, true ) ) {
		$modified = true;
		continue;
	}

	// If a class has already been seen then skip it; it should not be added twice.
	if ( in_array( $comparable_class_name, $seen, true ) ) {
		continue;
	}

	$seen[] = $comparable_class_name;

	/*
	 * Otherwise, append it to the new "class" attribute value.
	 *
	 * There are options for handling whitespace between tags.
	 * Preserving the existing whitespace produces fewer changes
	 * to the HTML content and should clarify the before/after
	 * content when debugging the modified output.
	 *
	 * This approach contrasts normalizing the inter-class
	 * whitespace to a single space, which might appear cleaner
	 * in the output HTML but produce a noisier change.
	 */
	if ( '' !== $class ) {
		$class .= substr( $existing_class, $ws_at, $ws_length );
	}
	$class .= $name;
}

// Add new classes by appending those which haven't already been seen.
foreach ( $this->classname_updates as $name => $operation ) {
	$comparable_name = $is_quirks ? strtolower( $name ) : $name;
	if ( self::ADD_CLASS === $operation && ! in_array( $comparable_name, $seen, true ) ) {
		$modified = true;

		$class .= strlen( $class ) > 0 ? ' ' : '';
		$class .= $name;
	}
}

$this->classname_updates = array();
if ( ! $modified ) {
	return;

Changelog

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

User Contributed Notes

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