Dustin Wilson
3 years ago
6 changed files with 124 additions and 703 deletions
@ -1,519 +0,0 @@ |
|||||
<?php |
|
||||
/** |
|
||||
* @license MIT |
|
||||
* Copyright 2017, Dustin Wilson, J. King et al. |
|
||||
* See LICENSE and AUTHORS files for details |
|
||||
*/ |
|
||||
|
|
||||
declare(strict_types=1); |
|
||||
namespace MensBeam\HTML\DOM; |
|
||||
use MensBeam\HTML\Parser; |
|
||||
|
|
||||
|
|
||||
class Element extends \DOMElement { |
|
||||
use DocumentOrElement, MagicProperties, Moonwalk, ParentNode, ToString, Walk; |
|
||||
|
|
||||
protected $_classList; |
|
||||
|
|
||||
|
|
||||
protected function __get_classList(): ?TokenList { |
|
||||
// MensBeam\HTML\DOM\TokenList uses WeakReference to prevent a circular reference, |
|
||||
// so it requires PHP 7.4 to work. |
|
||||
if (version_compare(\PHP_VERSION, '7.4.0', '>=')) { |
|
||||
// Only create the class list if it is actually used. |
|
||||
if ($this->_classList === null) { |
|
||||
$this->_classList = new TokenList($this, 'class'); |
|
||||
} |
|
||||
return $this->_classList; |
|
||||
} |
|
||||
return null; // @codeCoverageIgnore |
|
||||
} |
|
||||
|
|
||||
protected function __get_innerHTML(): string { |
|
||||
### DOM Parsing Specification ### |
|
||||
# 2.3 The InnerHTML mixin |
|
||||
# |
|
||||
# On getting, return the result of invoking the fragment serializing algorithm |
|
||||
# on the context object providing true for the require well-formed flag (this |
|
||||
# might throw an exception instead of returning a string). |
|
||||
// DEVIATION: Parsing of XML documents will not be handled by this |
|
||||
// implementation, so there's no need for the well-formed flag. |
|
||||
return $this->ownerDocument->saveHTML($this); |
|
||||
} |
|
||||
|
|
||||
protected function __set_innerHTML(string $value) { |
|
||||
### DOM Parsing Specification ### |
|
||||
# 2.3 The InnerHTML mixin |
|
||||
# |
|
||||
# On setting, these steps must be run: |
|
||||
# 1. Let context element be the context object's host if the context object is a |
|
||||
# ShadowRoot object, or the context object otherwise. |
|
||||
// DEVIATION: There is no scripting in this implementation. |
|
||||
|
|
||||
# 2. Let fragment be the result of invoking the fragment parsing algorithm with |
|
||||
# the new value as markup, and with context element. |
|
||||
$fragment = Parser::parseFragment($this, $this->ownerDocument->quirksMode, $value, 'UTF-8'); |
|
||||
$fragment = $this->ownerDocument->importNode($fragment); |
|
||||
|
|
||||
# 3. If the context object is a template element, then let context object be the |
|
||||
# template's template contents (a DocumentFragment). |
|
||||
if ($this->nodeName === 'template') { |
|
||||
$this->content = $fragment; |
|
||||
} |
|
||||
# 4. Replace all with fragment within the context object. |
|
||||
else { |
|
||||
# To replace all with a node within a parent, run these steps: |
|
||||
# |
|
||||
# 1. Let removedNodes be parent’s children. |
|
||||
// DEVIATION: removedNodes is used below for scripting. There is no scripting in |
|
||||
// this implementation. |
|
||||
|
|
||||
# 2. Let addedNodes be parent’s children. |
|
||||
// DEVIATION: addedNodes is used below for scripting. There is no scripting in |
|
||||
// this implementation. |
|
||||
|
|
||||
# 3. If node is a DocumentFragment node, then set addedNodes to node’s |
|
||||
# children. |
|
||||
|
|
||||
// DEVIATION: Again, there is no scripting in this implementation. |
|
||||
# 4. Otherwise, if node is non-null, set addedNodes to « node ». |
|
||||
// DEVIATION: Yet again, there is no scripting in this implementation. |
|
||||
|
|
||||
# 5. Remove all parent’s children, in tree order, with the suppress observers |
|
||||
# flag set. |
|
||||
// DEVIATION: There are no observers to suppress as there is no scripting in |
|
||||
// this implementation. |
|
||||
while ($this->hasChildNodes()) { |
|
||||
$this->removeChild($this->firstChild); |
|
||||
} |
|
||||
|
|
||||
# 6. Otherwise, if node is non-null, set addedNodes to « node ». |
|
||||
# If node is non-null, then insert node into parent before null with the |
|
||||
# suppress observers flag set. |
|
||||
// DEVIATION: Yet again, there is no scripting in this implementation. |
|
||||
|
|
||||
# 7. If either addedNodes or removedNodes is not empty, then queue a tree |
|
||||
# mutation record for parent with addedNodes, removedNodes, null, and null. |
|
||||
// DEVIATION: Normally the tree mutation record would do the actual replacement, |
|
||||
// but there is no scripting in this implementation. Going to simply append the |
|
||||
// fragment instead. |
|
||||
$this->appendChild($fragment); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
protected function __get_nextElementSibling(): Element { |
|
||||
# The nextElementSibling getter steps are to return the first following sibling |
|
||||
# that is an element; otherwise null. |
|
||||
if ($this->parentNode !== null) { |
|
||||
$start = false; |
|
||||
foreach ($this->parentNode->childNodes as $child) { |
|
||||
if (!$start) { |
|
||||
if ($child->isSameNode($this)) { |
|
||||
$start = true; |
|
||||
} |
|
||||
|
|
||||
continue; |
|
||||
} |
|
||||
|
|
||||
if (!$child instanceof Element) { |
|
||||
continue; |
|
||||
} |
|
||||
|
|
||||
return $child; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
protected function __get_outerHTML(): string { |
|
||||
### DOM Parsing Specification ### |
|
||||
# 2.4 Extensions to the Element interface |
|
||||
# outerHTML |
|
||||
# |
|
||||
# On getting, return the result of invoking the fragment serializing algorithm |
|
||||
# on a fictional node whose only child is the context object providing true for |
|
||||
# the require well-formed flag (this might throw an exception instead of |
|
||||
# returning a string). |
|
||||
// DEVIATION: Parsing of XML documents will not be handled by this |
|
||||
// implementation, so there's no need for the well-formed flag. |
|
||||
return $this->__toString(); |
|
||||
} |
|
||||
|
|
||||
protected function __set_outerHTML(string $value) { |
|
||||
### DOM Parsing Specification ### |
|
||||
# 2.4 Extensions to the Element interface |
|
||||
# outerHTML |
|
||||
# |
|
||||
# On setting, the following steps must be run: |
|
||||
# 1. Let parent be the context object's parent. |
|
||||
$parent = $this->parentNode; |
|
||||
|
|
||||
# 2. If parent is null, terminate these steps. There would be no way to obtain a |
|
||||
# reference to the nodes created even if the remaining steps were run. |
|
||||
// The spec is unclear here as to what to do. What do you return? Most browsers |
|
||||
// throw an exception here, so that's what we're going to do. |
|
||||
if ($parent === null) { |
|
||||
throw new DOMException(DOMException::OUTER_HTML_FAILED_NOPARENT); |
|
||||
} |
|
||||
# 3. If parent is a Document, throw a "NoModificationAllowedError" DOMException. |
|
||||
elseif ($parent instanceof Document) { |
|
||||
throw new DOMException(DOMException::NO_MODIFICATION_ALLOWED); |
|
||||
} |
|
||||
# 4. parent is a DocumentFragment, let parent be a new Element with: |
|
||||
# • body as its local name, |
|
||||
# • The HTML namespace as its namespace, and |
|
||||
# • The context object's node document as its node document. |
|
||||
elseif ($parent instanceof DocumentFragment) { |
|
||||
$parent = $this->ownerDocument->createElement('body'); |
|
||||
} |
|
||||
|
|
||||
# 5. Let fragment be the result of invoking the fragment parsing algorithm with |
|
||||
# the new value as markup, and parent as the context element. |
|
||||
$fragment = Parser::parseFragment($parent, $this->ownerDocument->quirksMode, $value, 'UTF-8'); |
|
||||
$fragment = $this->ownerDocument->importNode($fragment); |
|
||||
|
|
||||
# 6. Replace the context object with fragment within the context object's |
|
||||
# parent. |
|
||||
$this->parentNode->replaceChild($fragment, $this); |
|
||||
} |
|
||||
|
|
||||
protected function __get_previousElementSibling(): Element { |
|
||||
# The previousElementSibling getter steps are to return the first preceding |
|
||||
# sibling that is an element; otherwise null. |
|
||||
if ($this->parentNode !== null) { |
|
||||
foreach ($this->parentNode->childNodes as $child) { |
|
||||
if ($child->isSameNode($this)) { |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
if (!$child instanceof Element) { |
|
||||
continue; |
|
||||
} |
|
||||
|
|
||||
return $child; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
public function getAttribute(string $qualifiedName): ?string { |
|
||||
# The getAttribute(qualifiedName) method steps are: |
|
||||
# |
|
||||
# 1. Let attr be the result of getting an attribute given qualifiedName and this. |
|
||||
$attr = $this->getAttributeNode($qualifiedName); |
|
||||
# 2. If attr is null, return null. |
|
||||
if ($attr === null) { |
|
||||
return null; |
|
||||
} |
|
||||
# 3. Return attr’s value. |
|
||||
// Uncoerce the value if necessary. |
|
||||
return (!strpos($attr->value, 'U')) ? $attr->value : $this->uncoerceName($attr->value); |
|
||||
} |
|
||||
|
|
||||
public function getAttributeNode(string $qualifiedName): ?\DOMAttr { |
|
||||
# The getAttributeNode(qualifiedName) method steps are to return the result of |
|
||||
# getting an attribute given qualifiedName and this. |
|
||||
# |
|
||||
# To get an attribute by name given a qualifiedName and element element, run |
|
||||
# these steps: |
|
||||
# |
|
||||
# 1. If element is in the HTML namespace and its node document is an HTML document, |
|
||||
# then set qualifiedName to qualifiedName in ASCII lowercase. |
|
||||
// Document will always be an HTML document |
|
||||
if ($this->isHTMLNamespace()) { |
|
||||
$qualifiedName = strtolower($qualifiedName); |
|
||||
} |
|
||||
|
|
||||
# 2. Return the first attribute in element’s attribute list whose qualified name is |
|
||||
# qualifiedName; otherwise null. |
|
||||
// Going to try to handle this by getting the PHP DOM to do the heavy lifting |
|
||||
// when we can because it's faster. Also, check to see if the node's name was |
|
||||
// coerced. |
|
||||
try { |
|
||||
$value = parent::getAttributeNode($qualifiedName); |
|
||||
} catch (\DOMException $e) { |
|
||||
// The attribute name is invalid for XML |
|
||||
// Replace any offending characters with "UHHHHHH" where H are the |
|
||||
// uppercase hexadecimal digits of the character's code point |
|
||||
$qualifiedName = $this->coerceName($qualifiedName); |
|
||||
$value = parent::getAttributeNode($qualifiedName); |
|
||||
} |
|
||||
|
|
||||
if ($value === false && !parent::hasAttribute($qualifiedName)) { |
|
||||
// The PHP DOM does not acknowledge the presence of XMLNS-namespace attributes. |
|
||||
foreach ($this->attributes as $a) { |
|
||||
if ($a->nodeName === $qualifiedName) { |
|
||||
return $a; |
|
||||
} |
|
||||
} |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
return ($value !== false) ? $value : null; |
|
||||
} |
|
||||
|
|
||||
public function getAttributeNodeNS(?string $namespace = null, string $localName): ?\DOMAttr { |
|
||||
# The getAttributeNodeNS(namespace, localName) method steps are to return the |
|
||||
# result of getting an attribute given namespace, localName, and this. |
|
||||
# |
|
||||
# To get an attribute by namespace and local name given a namespace, localName, |
|
||||
# and element element, run these steps: |
|
||||
# |
|
||||
# 1. If namespace is the empty string, then set it to null. |
|
||||
if ($namespace === '') { |
|
||||
$namespace = null; |
|
||||
} |
|
||||
|
|
||||
# 2. Return the attribute in element’s attribute list whose namespace is namespace |
|
||||
# and local name is localName, if any; otherwise null. |
|
||||
// Going to try to handle this by getting the PHP DOM to do the heavy lifting |
|
||||
// when we can because it's faster. Also, check to see if the node's namespace |
|
||||
// and localName was coerced. |
|
||||
try { |
|
||||
$value = parent::getAttributeNodeNS($namespace, $localName); |
|
||||
} catch (\DOMException $e) { |
|
||||
// The attribute name is invalid for XML |
|
||||
// Replace any offending characters with "UHHHHHH" where H are the |
|
||||
// uppercase hexadecimal digits of the character's code point |
|
||||
$namespace = $this->coerceName($namespace); |
|
||||
$localName = $this->coerceName($localName); |
|
||||
$value = parent::getAttributeNodeNS($namespace, $localName); |
|
||||
} |
|
||||
|
|
||||
if ($value === false && !parent::hasAttributeNS($namespace, $localName)) { |
|
||||
// The PHP DOM does not acknowledge the presence of XMLNS-namespace attributes. |
|
||||
foreach ($this->attributes as $a) { |
|
||||
if ($a->namespaceURI === $namespace && $a->localName === $localName) { |
|
||||
return $a; |
|
||||
} |
|
||||
} |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
return ($value !== false) ? $value : null; |
|
||||
} |
|
||||
|
|
||||
public function getAttributeNS($namespaceURI, $localName) { |
|
||||
// Newer versions of the DOM spec have getAttributeNS return an empty string |
|
||||
// only when the attribute exists and is empty, otherwise null. This fixes that. |
|
||||
$value = parent::getAttributeNS($namespaceURI, $localName); |
|
||||
if ($value === '' && !$this->hasAttributeNS($namespaceURI, $localName)) { |
|
||||
return null; |
|
||||
} |
|
||||
return $value; |
|
||||
} |
|
||||
|
|
||||
public function hasAttribute(string $qualifiedName): bool { |
|
||||
# The hasAttribute(qualifiedName) method steps are: |
|
||||
# |
|
||||
# 1. If this is in the HTML namespace and its node document is an HTML document, |
|
||||
# then set qualifiedName to qualifiedName in ASCII lowercase. |
|
||||
// Document will always be an HTML document |
|
||||
if ($this->isHTMLNamespace()) { |
|
||||
$qualifiedName = strtolower($qualifiedName); |
|
||||
} |
|
||||
|
|
||||
# 2. Return true if this has an attribute whose qualified name is qualifiedName; |
|
||||
# otherwise false. |
|
||||
# An element has an attribute A if its attribute list contains A. |
|
||||
// Going to try to handle this by getting the PHP DOM to do the heavy lifting |
|
||||
// when we can because it's faster. Also, check to see if the node's name was |
|
||||
// coerced. |
|
||||
$value = parent::hasAttribute($this->coerceName($qualifiedName)); |
|
||||
if (!$value) { |
|
||||
// The PHP DOM does not acknowledge the presence of XMLNS-namespace attributes, |
|
||||
// so try it again. |
|
||||
$value = ($this->getAttributeNode($qualifiedName) !== null); |
|
||||
} |
|
||||
|
|
||||
return $value; |
|
||||
} |
|
||||
|
|
||||
public function setAttribute(string $qualifiedName, string $value): void { |
|
||||
# 1. If qualifiedName does not match the Name production in XML, then throw an |
|
||||
# "InvalidCharacterError" DOMException. |
|
||||
if (preg_match(self::$nameProductionRegex, $qualifiedName) !== 1) { |
|
||||
throw new DOMException(DOMException::INVALID_CHARACTER); |
|
||||
} |
|
||||
|
|
||||
# 2. If this is in the HTML namespace and its node document is an HTML document, |
|
||||
# then set qualifiedName to qualifiedName in ASCII lowercase. |
|
||||
// Document will always be an HTML document |
|
||||
if ($this->isHTMLNamespace()) { |
|
||||
$qualifiedName = strtolower($qualifiedName); |
|
||||
} |
|
||||
# 3. Let attribute be the first attribute in this’s attribute list whose |
|
||||
# qualified name is qualifiedName, and null otherwise. |
|
||||
# 4. If attribute is null, create an attribute whose local name is qualifiedName, |
|
||||
# value is value, and node document is this’s node document, then append this |
|
||||
# attribute to this, and then return. |
|
||||
# 5. Change attribute to value. |
|
||||
// Going to try to handle this by getting the PHP DOM to do the heavy lifting |
|
||||
// when we can because it's faster. But, first, we have to hack in classList |
|
||||
// support and then work around a couple of PHP bugs. |
|
||||
if ($this->isHTMLNamespace()) { |
|
||||
$qualifiedName = strtolower($qualifiedName); |
|
||||
|
|
||||
if ($qualifiedName === 'class' && $this->_classList !== null) { |
|
||||
$this->_classList->value = $value; |
|
||||
return; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
try { |
|
||||
parent::setAttributeNS(null, $qualifiedName, $value); |
|
||||
} catch (\DOMException $e) { |
|
||||
// The attribute name is invalid for XML |
|
||||
// Replace any offending characters with "UHHHHHH" where H are the |
|
||||
// uppercase hexadecimal digits of the character's code point |
|
||||
parent::setAttributeNS(null, $this->coerceName($qualifiedName), $value); |
|
||||
} |
|
||||
|
|
||||
// If you create an id attribute this way it won't be used by PHP in |
|
||||
// getElementById, so let's fix that. |
|
||||
if ($qualifiedName === 'id' && $namespaceURI === null) { |
|
||||
$this->setIdAttribute($qualifiedName, true); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public function setAttributeNS(?string $namespace, string $qualifiedName, string $value): void { |
|
||||
# 1. Let namespace, prefix, and localName be the result of passing namespace and |
|
||||
# qualifiedName to validate and extract. |
|
||||
[ 'namespace' => $namespace, 'prefix' => $prefix, 'localName' => $localName ] = $this->validateAndExtract($qualifiedName, $namespace); |
|
||||
$qualifiedName = ($prefix === null) ? $localName : "{$prefix}:{$localName}"; |
|
||||
|
|
||||
# 2. Set an attribute value for this using localName, value, and also prefix and |
|
||||
# namespace. |
|
||||
// Going to try to handle this by getting the PHP DOM to do the heavy lifting |
|
||||
// when we can because it's faster. But, first, we have to hack in classList |
|
||||
// support and then work around a couple of PHP bugs. |
|
||||
if ($this->isHTMLNamespace() && $qualifiedName === 'class' && $this->_classList !== null) { |
|
||||
$this->_classList->value = $value; |
|
||||
} elseif ($namespace === Parser::XMLNS_NAMESPACE) { |
|
||||
// NOTE: We create attribute nodes so that xmlns attributes |
|
||||
// don't get lost; otherwise they cannot be serialized |
|
||||
$a = @$this->ownerDocument->createAttributeNS($namespace, $qualifiedName); |
|
||||
if ($a === false) { |
|
||||
// The document element does not exist yet, so we need |
|
||||
// to insert this element into the document |
|
||||
$this->ownerDocument->appendChild($this); |
|
||||
$a = $this->ownerDocument->createAttributeNS($namespace, $qualifiedName); |
|
||||
$this->ownerDocument->removeChild($this); |
|
||||
} |
|
||||
$a->value = $this->escapeString($value, true); |
|
||||
$this->setAttributeNodeNS($a); |
|
||||
} else { |
|
||||
try { |
|
||||
parent::setAttributeNS($namespace, $qualifiedName, $value); |
|
||||
} catch (\DOMException $e) { |
|
||||
// The attribute name is invalid for XML |
|
||||
// Replace any offending characters with "UHHHHHH" where H are the |
|
||||
// uppercase hexadecimal digits of the character's code point |
|
||||
if ($namespace !== null && $namespace !== Parser::HTML_NAMESPACE) { |
|
||||
$qualifiedName = implode(':', array_map([$this, 'coerceName'], explode(':', $qualifiedName, 2))); |
|
||||
} else { |
|
||||
$qualifiedName = $this->coerceName($qualifiedName); |
|
||||
} |
|
||||
parent::setAttributeNS($namespace, $qualifiedName, $value); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if ($qualifiedName === 'id' && $namespaceURI === null) { |
|
||||
$this->setIdAttribute($qualifiedName, true); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/*public function hasAttributeNS(?string $namespace = null, string $localName) { |
|
||||
if (!parent::hasAttributeNS($namespace, $localName)) { |
|
||||
foreach ($this->attributes as $a) { |
|
||||
if (($a->namespaceURI === $namespace || (strpos($a->namespaceURI, 'U') !== false && $a->namespaceURI === $this->coerceName($namespaceURI))) && ($a->localName === $localName || (strpos($a->localName, 'U') !== false && $a->localName === $this->coerceName($localName)))) { |
|
||||
return true; |
|
||||
} |
|
||||
} |
|
||||
return false; |
|
||||
} |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
public function setAttribute($name, $value) { |
|
||||
$this->setAttributeNS(null, $name, $value); |
|
||||
} |
|
||||
|
|
||||
public function setAttributeNS($namespaceURI, $qualifiedName, $value) { |
|
||||
// Normalize the attribute name and namespace URI per modern DOM specifications. |
|
||||
if ($namespaceURI !== null) { |
|
||||
$namespaceURI = trim($namespaceURI); |
|
||||
} |
|
||||
$qualifiedName = trim($qualifiedName); |
|
||||
if ($namespaceURI === null && ($this->namespaceURI ?? Parser::HTML_NAMESPACE) === Parser::HTML_NAMESPACE && !$this->hasAttributeNS($namespaceURI, $qualifiedName)) { |
|
||||
$qualifiedName = trim(strtolower($qualifiedName)); |
|
||||
} |
|
||||
// If setting a class attribute and classList has been invoked use classList to |
|
||||
// set it. |
|
||||
if ($qualifiedName === 'class' && $namespaceURI === null && $this->_classList !== null) { |
|
||||
$this->_classList->value = $value; |
|
||||
} elseif ($namespaceURI === Parser::XMLNS_NAMESPACE) { |
|
||||
// NOTE: We create attribute nodes so that xmlns attributes |
|
||||
// don't get lost; otherwise they cannot be serialized |
|
||||
$a = @$this->ownerDocument->createAttributeNS($namespaceURI, $qualifiedName); |
|
||||
if ($a === false) { |
|
||||
// The document element does not exist yet, so we need |
|
||||
// to insert this element into the document |
|
||||
$this->ownerDocument->appendChild($this); |
|
||||
$a = $this->ownerDocument->createAttributeNS($namespaceURI, $qualifiedName); |
|
||||
$this->ownerDocument->removeChild($this); |
|
||||
} |
|
||||
$a->value = $this->escapeString($value, true); |
|
||||
$this->setAttributeNodeNS($a); |
|
||||
} else { |
|
||||
try { |
|
||||
parent::setAttributeNS($namespaceURI, $qualifiedName, $value); |
|
||||
} catch (\DOMException $e) { |
|
||||
// The attribute name is invalid for XML |
|
||||
// Replace any offending characters with "UHHHHHH" where H are the |
|
||||
// uppercase hexadecimal digits of the character's code point |
|
||||
if ($namespaceURI !== null) { |
|
||||
$qualifiedName = implode(":", array_map([$this, "coerceName"], explode(":", $qualifiedName, 2))); |
|
||||
} else { |
|
||||
$qualifiedName = $this->coerceName($qualifiedName); |
|
||||
} |
|
||||
parent::setAttributeNS($namespaceURI, $qualifiedName, $value); |
|
||||
} |
|
||||
if ($qualifiedName === "id" && $namespaceURI === null) { |
|
||||
$this->setIdAttribute($qualifiedName, true); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public function setAttributeNode(\DOMAttr $attribute) { |
|
||||
return $this->setAttributeNodeNS($attribute, null); |
|
||||
} |
|
||||
|
|
||||
public function setAttributeNodeNS(\DOMAttr $attribute) { |
|
||||
$fixId = false; |
|
||||
if ($attribute->namespaceURI === null) { |
|
||||
if ($attribute->name === 'id') { |
|
||||
$fixId = true; |
|
||||
} |
|
||||
// If appending a class attribute node, and classList has been invoked set |
|
||||
// the class using classList instead of appending the attribute node. Will |
|
||||
// return the created node instead. TokenList appends an attribute node |
|
||||
// internally to set the class attribute, so to prevent an infinite call loop |
|
||||
// from occurring, a check between the normalized value and classList's |
|
||||
// serialized value is performed. The spec is vague on how this is supposed to |
|
||||
// be handled. |
|
||||
elseif ($this->_classList !== null && $attribute->name === 'class' && preg_replace(Data::WHITESPACE_REGEX, ' ', $attribute->value) !== $this->_classList->value) { |
|
||||
$this->_classList->value = $attribute->value; |
|
||||
return $this->getAttributeNode('class'); |
|
||||
} |
|
||||
} |
|
||||
$result = parent::setAttributeNodeNS($attribute); |
|
||||
if ($fixId) { |
|
||||
$this->setIdAttribute($attribute->name, true); |
|
||||
} |
|
||||
return $result; |
|
||||
}*/ |
|
||||
} |
|
Loading…
Reference in new issue