Browse Source

Fixing minor bugs

wrapper-classes
Dustin Wilson 3 years ago
parent
commit
1373c776c0
  1. 39
      lib/DocumentOrElement.php

39
lib/DocumentOrElement.php

@ -23,6 +23,13 @@ use MensBeam\HTML\Parser\Data;
trait DocumentOrElement {
public function getElementsByClassName(string $classNames): HTMLCollection {
$innerNode = $this->innerNode;
if ($this instanceof Document) {
$doc = $innerNode;
$wrapperDoc = $this;
} else {
$doc = $innerNode->ownerDocument;
$wrapperDoc = $this->ownerDocument;
}
# The list of elements with class names classNames for a node root is the
# HTMLCollection returned by the following algorithm:
@ -33,15 +40,7 @@ trait DocumentOrElement {
##
## 1. Let inputTokens be the result of splitting input on ASCII whitespace.
// There isn't a Set object in php, so make sure all the tokens are unique.
$inputTokens = ($classNames !== '') ? array_unique(preg_split(Data::WHITESPACE_REGEX, $classNames)) : [];
if ($this instanceof Document) {
$doc = $innerNode;
$wrapperDoc = $this;
} else {
$doc = $innerNode->ownerDocument;
$wrapperDoc = $this->ownerDocument;
}
$inputTokens = ($classNames !== '') ? array_unique(preg_split(Data::WHITESPACE_REGEX, ($wrapperDoc->compatMode !== 'BackCompat') ? $classNames : strtolower($classNames))) : [];
## 2. Let tokens be a new ordered set.
## 3. For each token in inputTokens, append token to tokens.
@ -49,27 +48,27 @@ trait DocumentOrElement {
// There isn't a Set object in php, so just use the uniqued input tokens.
# 2. If classes is the empty set, return an empty HTMLCollection.
if ($inputTokens === []) {
if ($inputTokens === [] || $inputTokens === [ '' ]) {
return Reflection::createFromProtectedConstructor(__NAMESPACE__ . '\\HTMLCollection', $doc, new \DOMNodeList());
}
# 3. Return a HTMLCollection rooted at root, whose filter matches descendant
# elements that have all their classes in classes.
#
# The comparisons for the classes must be done in an ASCII case-insensitive manner
# if root’s node document’s mode is "quirks"; otherwise in an identical to manner.
// It's just faster to use XPath to create the a nodelist that will then be
// wrapped instead of polling a closure containing a DOM walker that has to then
// explode each and every class string by whitespace and then iterate through
// them... yeah not gonna do that.
foreach ($inputTokens as &$token) {
if ($wrapperDoc->compatMode === 'BackCompat') {
$token = strtolower($token);
}
$token = "contains(concat(' ',normalize-space(@class),' '),' $token ')";
}
$query = './/*[' . implode(' and ', $inputTokens) . ']';
# The comparisons for the classes must be done in an ASCII case-insensitive manner
# if root’s node document’s mode is "quirks"; otherwise in an identical to manner.
// This is done earlier when exploding the classes. It's faster to do it before
// exploding than after...
$query = './/*[';
foreach ($inputTokens as $token) {
$query .= "contains(concat(' ',normalize-space(@class),' '),' $token ') and";
}
$query = substr($query, 0, -4) . ']';
return Reflection::createFromProtectedConstructor(__NAMESPACE__ . '\\HTMLCollection', $doc, (new \DOMXPath($this->getInnerDocument()))->query($query, $innerNode));
}

Loading…
Cancel
Save