Skip to content

Commit 2e81b2f

Browse files
committed
Work on complex selector handling
1 parent 95efc50 commit 2e81b2f

File tree

1 file changed

+44
-5
lines changed

1 file changed

+44
-5
lines changed

src/wp-includes/html-api/class-wp-css-selectors.php

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,11 +1033,47 @@ private static function parse_subclass_selector( string $input, int &$offset ) {
10331033
*/
10341034
final class WP_CSS_Complex_Selector extends WP_CSS_Selector_Parser {
10351035
public function matches( WP_HTML_Processor $processor ): bool {
1036-
// @todo this can throw on parse.
1037-
if ( count( $this->selectors ) > 1 ) {
1038-
throw new Exception( 'Combined complex selectors are not supported yet.' );
1036+
if ( count( $this->selectors ) === 1 ) {
1037+
return $this->selectors[0]->matches( $processor );
1038+
}
1039+
1040+
// First selector must match this location.
1041+
if ( ! $this->selectors[0]->matches( $processor ) ) {
1042+
return false;
1043+
}
1044+
1045+
$breadcrumbs = array_slice( array_reverse( $processor->get_breadcrumbs() ), 1 );
1046+
$selectors = array_slice( $this->selectors, 1 );
1047+
return $this->explore_matches( $selectors, $breadcrumbs );
1048+
}
1049+
1050+
/**
1051+
* This only looks at breadcrumbs and can therefore only support type selectors.
1052+
*
1053+
* @param array<WP_CSS_Selector> $selectors
1054+
*/
1055+
private function explore_matches( array $selectors, array $breadcrumbs ): bool {
1056+
if ( array() === $selectors ) {
1057+
return true;
1058+
}
1059+
if ( array() === $breadcrumbs ) {
1060+
return false;
1061+
}
1062+
1063+
$combinator = $selectors[0];
1064+
$selector = $selectors[1];
1065+
1066+
switch ( $combinator ) {
1067+
case self::COMBINATOR_CHILD:
1068+
if ( '*' === $selector->type_selector->ident || strcasecmp( $breadcrumbs[0], $selector->type_selector->ident ) === 0 ) {
1069+
return $this->explore_matches( array_slice( $selectors, 2 ), array_slice( $breadcrumbs, 1 ) );
1070+
}
1071+
return $this->explore_matches( $selectors, array_slice( $breadcrumbs, 1 ) );
1072+
1073+
case self::COMBINATOR_DESCENDANT:
1074+
default:
1075+
throw new Exception( "Combinator '{$combinator}' is not supported yet." );
10391076
}
1040-
return $this->selectors[0]->matches( $processor );
10411077
}
10421078

10431079
const COMBINATOR_CHILD = '>';
@@ -1047,12 +1083,15 @@ public function matches( WP_HTML_Processor $processor ): bool {
10471083

10481084
/**
10491085
* even indexes are WP_CSS_Selector, odd indexes are string combinators.
1086+
* In reverse order to match the current element and then work up the tree.
1087+
* Any non-final selector is a type selector.
1088+
*
10501089
* @var array<WP_CSS_Selector>
10511090
*/
10521091
public $selectors = array();
10531092

10541093
private function __construct( array $selectors ) {
1055-
$this->selectors = $selectors;
1094+
$this->selectors = array_reverse( $selectors );
10561095
}
10571096

10581097
public static function parse( string $input, int &$offset ): ?self {

0 commit comments

Comments
 (0)