Skip to content

Commit 6d125ba

Browse files
ImangazalievImangazaliev
Imangazaliev
authored and
Imangazaliev
committed
Add ability to check that element matches selector
1 parent e742886 commit 6d125ba

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

src/DiDom/Element.php

+66
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,72 @@ public function count($expression, $type = Query::TYPE_CSS)
144144
return $this->toDocument()->count($expression, $type);
145145
}
146146

147+
/**
148+
* Checks that the node matches selector.
149+
*
150+
* @param string $selector CSS selector
151+
* @param bool $strict
152+
*
153+
* @return bool
154+
*/
155+
public function matches($selector, $strict = false)
156+
{
157+
if (!$strict) {
158+
// remove child nodes
159+
$node = $this->node->cloneNode();
160+
161+
$innerHtml = $node->ownerDocument->saveXml($node, LIBXML_NOEMPTYTAG);
162+
$html = "<root>$innerHtml</root>";
163+
164+
$selector = 'root > '.trim($selector);
165+
166+
$document = new Document($html);
167+
168+
return $document->has($selector);
169+
}
170+
171+
$segments = Query::getSegments($selector);
172+
173+
$segments['tag'] = array_key_exists('tag', $segments) ? $segments['tag'] : null;
174+
175+
if ($segments['tag'] !== $this->tag and $segments['tag'] !== '*') {
176+
return false;
177+
}
178+
179+
$segments['id'] = array_key_exists('id', $segments) ? $segments['id'] : null;
180+
181+
if ($segments['id'] !== $this->getAttribute('id')) {
182+
return false;
183+
}
184+
185+
$classes = $this->hasAttribute('class') ? explode(' ', trim($this->getAttribute('class'))) : [];
186+
187+
$segments['classes'] = array_key_exists('classes', $segments) ? $segments['classes'] : [];
188+
189+
$diff1 = array_diff($segments['classes'], $classes);
190+
$diff2 = array_diff($classes, $segments['classes']);
191+
192+
if (count($diff1) > 0 or count($diff2) > 0) {
193+
return false;
194+
}
195+
196+
$attributes = $this->attributes();
197+
198+
unset($attributes['id']);
199+
unset($attributes['class']);
200+
201+
$segments['attributes'] = array_key_exists('attributes', $segments) ? $segments['attributes'] : [];
202+
203+
$diff1 = array_diff_assoc($segments['attributes'], $attributes);
204+
$diff2 = array_diff_assoc($attributes, $segments['attributes']);
205+
206+
if (count($diff1) > 0 or count($diff2) > 0) {
207+
return false;
208+
}
209+
210+
return true;
211+
}
212+
147213
/**
148214
* Determine if an attribute exists on the element.
149215
*

tests/DiDom/ElementTest.php

+23
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,29 @@ public function testCount()
195195
$this->assertEquals(0, $document->count('li'));
196196
}
197197

198+
public function testMatches()
199+
{
200+
$element = new Element('ul', null, ['id' => 'foo', 'class' => 'bar baz']);
201+
202+
$this->assertTrue($element->matches('ul'));
203+
$this->assertTrue($element->matches('#foo'));
204+
$this->assertTrue($element->matches('.bar'));
205+
$this->assertTrue($element->matches('ul#foo.bar.baz'));
206+
$this->assertFalse($element->matches('a#foo.bar.baz'));
207+
208+
// strict
209+
$this->assertTrue($element->matches('ul#foo.bar.baz', true));
210+
$this->assertFalse($element->matches('ul#foo.bar', true));
211+
$this->assertFalse($element->matches('ul#foo', true));
212+
$this->assertFalse($element->matches('ul.bar.baz', true));
213+
$this->assertFalse($element->matches('#foo.bar.baz', true));
214+
$this->assertFalse($element->matches('ul.bar.baz', true));
215+
216+
$element = new Element('p');
217+
218+
$this->assertTrue($element->matches('p', true));
219+
}
220+
198221
public function testHasAttribute()
199222
{
200223
$node = $this->createNode('input');

0 commit comments

Comments
 (0)