Splits the CSS selector into parts (tag name, ID, classes, attributes, pseudo-class).
public static getSegments ( string $selector ) : array | ||
$selector | string | CSS selector |
return | array |
/** * Create new element node by CSS selector. * * @param string $selector * @param string $value * @param array $attributes * * @return \DiDom\Element */ public function createElementBySelector($selector, $value = null, $attributes = []) { $segments = Query::getSegments($selector); $name = array_key_exists('tag', $segments) ? $segments['tag'] : 'div'; if (array_key_exists('attributes', $segments)) { $attributes = array_merge($attributes, $segments['attributes']); } if (array_key_exists('id', $segments)) { $attributes['id'] = $segments['id']; } if (array_key_exists('classes', $segments)) { $attributes['class'] = implode(' ', $segments['classes']); } return $this->createElement($name, $value, $attributes); }
/** * @dataProvider invalidSelectorProvider */ public function testInvalidSelector($selector) { $this->setExpectedException('RuntimeException'); var_dump(Query::getSegments($selector)); }
/** * @dataProvider segmentsProvider */ public function testGetSegments($selector, $segments) { $this->assertEquals($segments, Query::getSegments($selector)); }
/** * Checks that the node matches selector. * * @param string $selector CSS selector * @param bool $strict * * @return bool */ public function matches($selector, $strict = false) { if (!$strict) { // remove child nodes $node = $this->node->cloneNode(); if (!$this->node instanceof \DOMElement) { throw new LogicException('Node must be an instance of DOMElement'); } $innerHtml = $node->ownerDocument->saveXml($node, LIBXML_NOEMPTYTAG); $html = "<root>{$innerHtml}</root>"; $selector = 'root > ' . trim($selector); $document = new Document($html); return $document->has($selector); } $segments = Query::getSegments($selector); if (!array_key_exists('tag', $segments)) { throw new RuntimeException(sprintf('Tag name must be specified in %s', $selector)); } if ($segments['tag'] !== $this->tag and $segments['tag'] !== '*') { return false; } $segments['id'] = array_key_exists('id', $segments) ? $segments['id'] : null; if ($segments['id'] !== $this->getAttribute('id')) { return false; } $classes = $this->hasAttribute('class') ? explode(' ', trim($this->getAttribute('class'))) : []; $segments['classes'] = array_key_exists('classes', $segments) ? $segments['classes'] : []; $diff1 = array_diff($segments['classes'], $classes); $diff2 = array_diff($classes, $segments['classes']); if (count($diff1) > 0 or count($diff2) > 0) { return false; } $attributes = $this->attributes(); unset($attributes['id']); unset($attributes['class']); $segments['attributes'] = array_key_exists('attributes', $segments) ? $segments['attributes'] : []; $diff1 = array_diff_assoc($segments['attributes'], $attributes); $diff2 = array_diff_assoc($attributes, $segments['attributes']); if (count($diff1) > 0 or count($diff2) > 0) { return false; } return true; }
/** * @param string CSS selector * @param array * * @return NodeList */ public function findByRule($selector, $rules, $wrapElement = true) { $segments = $selector !== null ? Query::getSegments($selector) : []; $xpath = Query::buildXpath(array_merge($segments, $rules)); return $this->xpath($xpath, $wrapElement); }
/** * @expectedException RuntimeException */ public function testGetSegmentsWithEmptyClass() { Query::getSegments('.'); }