Skip to content

Commit 4a267e3

Browse files
committed
Fixed issue paquettg#65
1 parent a4f557d commit 4a267e3

File tree

4 files changed

+30
-7
lines changed

4 files changed

+30
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
- Added `declare(strict_types=1)` to all source files.
1313
- Added new option `depthFirstSearch`.
1414
- Deprecated option `depthFirstSearch` and marked for removal in `3.0.0`.
15+
- Added multi class selections support.
1516

1617
### Changed
1718
- Started using a changelog.

src/PHPHtmlParser/Selector/Parser.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class Parser implements ParserInterface
1414
*
1515
* @var string
1616
*/
17-
protected $pattern = "/([\w\-:\*>]*)(?:\#([\w\-]+)|\.([\w\-]+))?(?:\[@?(!?[\w\-:]+)(?:([!*^$]?=)[\"']?(.*?)[\"']?)?\])?([\/, ]+)/is";
17+
protected $pattern = "/([\w\-:\*>]*)(?:\#([\w\-]+)|\.([\w\.\-]+))?(?:\[@?(!?[\w\-:]+)(?:([!*^$]?=)[\"']?(.*?)[\"']?)?\])?([\/, ]+)/is";
1818

1919
/**
2020
* Parses the selector string
@@ -53,7 +53,7 @@ public function parseSelectorString(string $selector): array
5353
// check for class selector
5454
if ( ! empty($match[3])) {
5555
$key = 'class';
56-
$value = $match[3];
56+
$value = explode('.', $match[3]);
5757
}
5858

5959
// and final attribute selector

src/PHPHtmlParser/Selector/Selector.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -343,16 +343,24 @@ public function checkComparison(array $rule, AbstractNode $node): bool
343343
$nodeValue = $node->getAttribute($rule['key']);
344344
}
345345

346-
$check = $this->match($rule['operator'], $rule['value'], $nodeValue);
346+
$check = false;
347+
if (!is_array($rule['value'])) {
348+
$check = $this->match($rule['operator'], $rule['value'], $nodeValue);
349+
}
347350

348351
// handle multiple classes
349352
if ( ! $check && $rule['key'] == 'class') {
350353
$nodeClasses = explode(' ', $node->getAttribute('class'));
351-
foreach ($nodeClasses as $class) {
352-
if ( ! empty($class)) {
353-
$check = $this->match($rule['operator'], $rule['value'], $class);
354+
foreach ($rule['value'] as $value) {
355+
foreach ($nodeClasses as $class) {
356+
if ( ! empty($class)) {
357+
$check = $this->match($rule['operator'], $value, $class);
358+
}
359+
if ($check) {
360+
break;
361+
}
354362
}
355-
if ($check) {
363+
if (!$check) {
356364
break;
357365
}
358366
}

tests/Selector/SelectorTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,4 +216,18 @@ public function testFindNodeByAttributeOnly()
216216
$selector = new Selector('[custom-attr]', new Parser());
217217
$this->assertEquals(1, count($selector->find($root)));
218218
}
219+
220+
public function testFindMultipleClasses()
221+
{
222+
$root = new HtmlNode(new Tag('root'));
223+
$child1 = new HtmlNode(new Tag('a'));
224+
$child1->setAttribute('class', 'b');
225+
$child2 = new HtmlNode(new Tag('a'));
226+
$child2->setAttribute('class', 'b c');
227+
$root->addChild($child1);
228+
$root->addChild($child2);
229+
230+
$selector = new Selector('a.b.c', new Parser());
231+
$this->assertEquals(1, count($selector->find($root)));
232+
}
219233
}

0 commit comments

Comments
 (0)