Implement DOMNode::getRootNode()

ref: https://dom.spec.whatwg.org/#dom-node-getrootnode

Closes GH-11693.
This commit is contained in:
Niels Dossche 2023-07-12 22:40:36 +02:00
parent 10d7e8dc3a
commit d17069e191
6 changed files with 71 additions and 1 deletions

1
NEWS
View File

@ -18,6 +18,7 @@ PHP NEWS
- DOM: - DOM:
. Added DOMNode::contains() and DOMNameSpaceNode::contains(). (nielsdos) . Added DOMNode::contains() and DOMNameSpaceNode::contains(). (nielsdos)
. Added DOMElement::getAttributeNames(). (nielsdos) . Added DOMElement::getAttributeNames(). (nielsdos)
. Added DOMNode::getRootNode(). (nielsdos)
- Intl: - Intl:
. Fix memory leak in MessageFormatter::format() on failure. (Girgias) . Fix memory leak in MessageFormatter::format() on failure. (Girgias)

View File

@ -243,6 +243,9 @@ PHP 8.3 UPGRADE NOTES
- DOM: - DOM:
. Added DOMNode::contains() and DOMNameSpaceNode::contains(). . Added DOMNode::contains() and DOMNameSpaceNode::contains().
. Added DOMElement::getAttributeNames(). . Added DOMElement::getAttributeNames().
. Added DOMNode::getRootNode(). The $options argument does nothing at the
moment because it only influences the shadow DOM, which we do not support
yet.
- JSON: - JSON:
. Added json_validate(), which returns whether the json is valid for . Added json_validate(), which returns whether the json is valid for

View File

@ -1818,4 +1818,30 @@ PHP_METHOD(DOMNode, contains)
} }
/* }}} */ /* }}} */
/* {{{ URL: https://dom.spec.whatwg.org/#dom-node-getrootnode
Since:
*/
PHP_METHOD(DOMNode, getRootNode)
{
zval *id;
xmlNodePtr thisp;
dom_object *intern;
/* Unused now because we don't support the shadow DOM nodes. Options only influence shadow DOM nodes. */
zval *options = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a!", &options) == FAILURE) {
RETURN_THROWS();
}
DOM_GET_THIS_OBJ(thisp, id, xmlNodePtr, intern);
while (thisp->parent) {
thisp = thisp->parent;
}
int ret;
DOM_RET_OBJ(thisp, &ret, intern);
}
/* }}} */
#endif #endif

View File

@ -391,6 +391,8 @@ class DOMNode
public function replaceChild(DOMNode $node, DOMNode $child) {} public function replaceChild(DOMNode $node, DOMNode $child) {}
public function contains(DOMNode|DOMNameSpaceNode|null $other): bool {} public function contains(DOMNode|DOMNameSpaceNode|null $other): bool {}
public function getRootNode(?array $options = null): DOMNode {}
} }
/** @not-serializable */ /** @not-serializable */

View File

@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead. /* This is a generated file, edit the .stub.php file instead.
* Stub hash: e3efd06d963e7a29d9869b7204133ccc8a22bf3b */ * Stub hash: bba8006906191fa0dd961d65460749a7c7f12afc */
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_dom_import_simplexml, 0, 1, DOMElement, 0) ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_dom_import_simplexml, 0, 1, DOMElement, 0)
ZEND_ARG_TYPE_INFO(0, node, IS_OBJECT, 0) ZEND_ARG_TYPE_INFO(0, node, IS_OBJECT, 0)
@ -104,6 +104,10 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_DOMNode_contains, 0, 1, _I
ZEND_ARG_OBJ_TYPE_MASK(0, other, DOMNode|DOMNameSpaceNode, MAY_BE_NULL, NULL) ZEND_ARG_OBJ_TYPE_MASK(0, other, DOMNode|DOMNameSpaceNode, MAY_BE_NULL, NULL)
ZEND_END_ARG_INFO() ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_DOMNode_getRootNode, 0, 0, DOMNode, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 1, "null")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DOMImplementation_getFeature, 0, 2, IS_NEVER, 0) ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DOMImplementation_getFeature, 0, 2, IS_NEVER, 0)
ZEND_ARG_TYPE_INFO(0, feature, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, feature, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, version, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, version, IS_STRING, 0)
@ -520,6 +524,7 @@ ZEND_METHOD(DOMNode, normalize);
ZEND_METHOD(DOMNode, removeChild); ZEND_METHOD(DOMNode, removeChild);
ZEND_METHOD(DOMNode, replaceChild); ZEND_METHOD(DOMNode, replaceChild);
ZEND_METHOD(DOMNode, contains); ZEND_METHOD(DOMNode, contains);
ZEND_METHOD(DOMNode, getRootNode);
ZEND_METHOD(DOMImplementation, getFeature); ZEND_METHOD(DOMImplementation, getFeature);
ZEND_METHOD(DOMImplementation, hasFeature); ZEND_METHOD(DOMImplementation, hasFeature);
ZEND_METHOD(DOMImplementation, createDocumentType); ZEND_METHOD(DOMImplementation, createDocumentType);
@ -703,6 +708,7 @@ static const zend_function_entry class_DOMNode_methods[] = {
ZEND_ME(DOMNode, removeChild, arginfo_class_DOMNode_removeChild, ZEND_ACC_PUBLIC) ZEND_ME(DOMNode, removeChild, arginfo_class_DOMNode_removeChild, ZEND_ACC_PUBLIC)
ZEND_ME(DOMNode, replaceChild, arginfo_class_DOMNode_replaceChild, ZEND_ACC_PUBLIC) ZEND_ME(DOMNode, replaceChild, arginfo_class_DOMNode_replaceChild, ZEND_ACC_PUBLIC)
ZEND_ME(DOMNode, contains, arginfo_class_DOMNode_contains, ZEND_ACC_PUBLIC) ZEND_ME(DOMNode, contains, arginfo_class_DOMNode_contains, ZEND_ACC_PUBLIC)
ZEND_ME(DOMNode, getRootNode, arginfo_class_DOMNode_getRootNode, ZEND_ACC_PUBLIC)
ZEND_FE_END ZEND_FE_END
}; };

View File

@ -0,0 +1,32 @@
--TEST--
DOMNode::getRootNode()
--EXTENSIONS--
dom
--FILE--
<?php
$dom = new DOMDocument();
$dom->loadXML('<?xml version="1.0"?><html><body/></html>');
var_dump($dom->documentElement->firstElementChild->getRootNode() === $dom);
$p = $dom->createElement('p');
var_dump($p->getRootNode() === $p);
$dom->documentElement->appendChild($p);
var_dump($p->getRootNode() === $dom);
$dom->documentElement->remove();
var_dump($p->getRootNode() === $p);
$fragment = $dom->createDocumentFragment();
var_dump($fragment->getRootNode() === $fragment);
$div = $fragment->appendChild($dom->createElement('div'));
$div->appendChild($p);
var_dump($p->getRootNode() === $fragment);
?>
--EXPECT--
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)