wpseek.com
A WordPress-centric search engine for devs and theme authors



wp_get_state_selector_ancestor › WordPress Function

Since7.2.0
Deprecatedn/a
› wp_get_state_selector_ancestor ( $selector, $block_name )
Parameters: (2)
  • (string) $selector A single block or feature selector.
    Required: Yes
  • (string|null) $block_name Name of the block being scoped.
    Required: Yes
Returns:
  • (string) The leading compound and its combinator, or an empty string.
Defined at:
Codex:

Returns the ancestor part of a block selector whose leading compound names a different block, e.g. `.wp-block-list > ` in List Item's `.wp-block-list > li`.

The block-instance class is on the block's own wrapper, so a leading compound naming another block must be kept rather than swapped for that class. When the next compound carries a wp-block-* class (.wp-block-button .wp-block-button__link), the selector describes a nested element and keeps the leading swap.


Source

function wp_get_state_selector_ancestor( $selector, $block_name ) {
	if (
		! is_string( $block_name ) ||
		'' === $block_name ||
		! preg_match( '/^\.(wp-block-[-_a-zA-Z0-9]+)/', $selector, $matches ) ||
		wp_get_block_default_classname( $block_name ) === $matches[1]
	) {
		return '';
	}

	$ancestor_length = 0;
	$next_compound   = '';
	$depth           = 0;
	$selector_length = strlen( $selector );

	for ( $i = 0; $i < $selector_length; $i++ ) {
		$char = $selector[ $i ];

		if ( '(' === $char || '[' === $char ) {
			++$depth;
		} elseif ( ( ')' === $char || ']' === $char ) && $depth > 0 ) {
			--$depth;
		} elseif ( 0 === $depth && str_contains( " \t\n\r\f>+~", $char ) ) {
			if ( $ancestor_length ) {
				break;
			}
			$ancestor_length = $i + strspn( $selector, " \t\n\r\f>+~", $i );
			$i               = $ancestor_length - 1;
		} elseif ( 0 === $depth && $ancestor_length ) {
			$next_compound .= $char;
		}
	}

	if ( '' === $next_compound || str_contains( $next_compound, '.wp-block-' ) ) {
		return '';
	}

	return substr( $selector, 0, $ancestor_length );
}