mirror of
https://github.com/php/php-src.git
synced 2024-11-23 18:04:36 +08:00
Implement DOMNode::isConnected and DOMNameSpaceNode::isConnected
ref: https://dom.spec.whatwg.org/#dom-node-isconnected Closes GH-11677.
This commit is contained in:
parent
9c5cf6594d
commit
d38cc9b9b6
1
NEWS
1
NEWS
@ -25,6 +25,7 @@ PHP NEWS
|
||||
. Added DOMNode::getRootNode(). (nielsdos)
|
||||
. Added DOMElement::className and DOMElement::id. (nielsdos)
|
||||
. Added DOMParentNode::replaceChildren(). (nielsdos)
|
||||
. Added DOMNode::isConnected and DOMNameSpaceNode::isConnected. (nielsdos)
|
||||
|
||||
- FPM:
|
||||
. Added warning to log when fpm socket was not registered on the expected
|
||||
|
@ -268,6 +268,7 @@ PHP 8.3 UPGRADE NOTES
|
||||
This is not binary-safe at the moment because of underlying limitations of
|
||||
libxml2.
|
||||
. Added DOMParentNode::replaceChildren().
|
||||
. Added DOMNode::isConnected and DOMNameSpaceNode::isConnected.
|
||||
|
||||
- JSON:
|
||||
. Added json_validate(), which returns whether the json is valid for
|
||||
|
@ -994,19 +994,6 @@ PHP_METHOD(DOMDocument, getElementsByTagNameNS)
|
||||
}
|
||||
/* }}} end dom_document_get_elements_by_tag_name_ns */
|
||||
|
||||
static bool php_dom_is_node_attached(const xmlNode *node)
|
||||
{
|
||||
ZEND_ASSERT(node != NULL);
|
||||
node = node->parent;
|
||||
while (node != NULL) {
|
||||
if (node->type == XML_DOCUMENT_NODE || node->type == XML_HTML_DOCUMENT_NODE) {
|
||||
return true;
|
||||
}
|
||||
node = node->parent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-getElBId
|
||||
Since: DOM Level 2
|
||||
*/
|
||||
@ -1035,7 +1022,7 @@ PHP_METHOD(DOMDocument, getElementById)
|
||||
* ingrained in the library, and uses the cache for various purposes, it seems like a bad
|
||||
* idea and lost cause to fight it. Instead, we'll simply walk the tree upwards to check
|
||||
* if the node is attached to the document. */
|
||||
if (attrp && attrp->parent && php_dom_is_node_attached(attrp->parent)) {
|
||||
if (attrp && attrp->parent && php_dom_is_node_connected(attrp->parent)) {
|
||||
DOM_RET_OBJ((xmlNodePtr) attrp->parent, &ret, intern);
|
||||
} else {
|
||||
RETVAL_NULL();
|
||||
|
@ -107,6 +107,7 @@ int dom_node_next_sibling_read(dom_object *obj, zval *retval);
|
||||
int dom_node_previous_element_sibling_read(dom_object *obj, zval *retval);
|
||||
int dom_node_next_element_sibling_read(dom_object *obj, zval *retval);
|
||||
int dom_node_attributes_read(dom_object *obj, zval *retval);
|
||||
zend_result dom_node_is_connected_read(dom_object *obj, zval *retval);
|
||||
int dom_node_owner_document_read(dom_object *obj, zval *retval);
|
||||
int dom_node_namespace_uri_read(dom_object *obj, zval *retval);
|
||||
int dom_node_prefix_read(dom_object *obj, zval *retval);
|
||||
|
@ -52,6 +52,18 @@ zend_string *dom_node_get_node_name_attribute_or_element(const xmlNode *nodep)
|
||||
}
|
||||
}
|
||||
|
||||
bool php_dom_is_node_connected(const xmlNode *node)
|
||||
{
|
||||
ZEND_ASSERT(node != NULL);
|
||||
do {
|
||||
if (node->type == XML_DOCUMENT_NODE || node->type == XML_HTML_DOCUMENT_NODE) {
|
||||
return true;
|
||||
}
|
||||
node = node->parent;
|
||||
} while (node != NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* {{{ nodeName string
|
||||
readonly=yes
|
||||
URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-F68D095
|
||||
@ -488,6 +500,25 @@ int dom_node_attributes_read(dom_object *obj, zval *retval)
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ isConnected boolean
|
||||
readonly=yes
|
||||
URL: https://dom.spec.whatwg.org/#dom-node-isconnected
|
||||
Since:
|
||||
*/
|
||||
zend_result dom_node_is_connected_read(dom_object *obj, zval *retval)
|
||||
{
|
||||
xmlNode *nodep = dom_object_get_node(obj);
|
||||
|
||||
if (nodep == NULL) {
|
||||
php_dom_throw_error(INVALID_STATE_ERR, 1);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
ZVAL_BOOL(retval, php_dom_is_node_connected(nodep));
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ ownerDocument DomDocument
|
||||
readonly=yes
|
||||
URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-node-ownerDoc
|
||||
|
@ -642,6 +642,7 @@ PHP_MINIT_FUNCTION(dom)
|
||||
dom_register_prop_handler(&dom_node_prop_handlers, "previousSibling", sizeof("previousSibling")-1, dom_node_previous_sibling_read, NULL);
|
||||
dom_register_prop_handler(&dom_node_prop_handlers, "nextSibling", sizeof("nextSibling")-1, dom_node_next_sibling_read, NULL);
|
||||
dom_register_prop_handler(&dom_node_prop_handlers, "attributes", sizeof("attributes")-1, dom_node_attributes_read, NULL);
|
||||
dom_register_prop_handler(&dom_node_prop_handlers, "isConnected", sizeof("isConnected")-1, dom_node_is_connected_read, NULL);
|
||||
dom_register_prop_handler(&dom_node_prop_handlers, "ownerDocument", sizeof("ownerDocument")-1, dom_node_owner_document_read, NULL);
|
||||
dom_register_prop_handler(&dom_node_prop_handlers, "namespaceURI", sizeof("namespaceURI")-1, dom_node_namespace_uri_read, NULL);
|
||||
dom_register_prop_handler(&dom_node_prop_handlers, "prefix", sizeof("prefix")-1, dom_node_prefix_read, dom_node_prefix_write);
|
||||
@ -660,6 +661,7 @@ PHP_MINIT_FUNCTION(dom)
|
||||
dom_register_prop_handler(&dom_namespace_node_prop_handlers, "prefix", sizeof("prefix")-1, dom_node_prefix_read, NULL);
|
||||
dom_register_prop_handler(&dom_namespace_node_prop_handlers, "localName", sizeof("localName")-1, dom_node_local_name_read, NULL);
|
||||
dom_register_prop_handler(&dom_namespace_node_prop_handlers, "namespaceURI", sizeof("namespaceURI")-1, dom_node_namespace_uri_read, NULL);
|
||||
dom_register_prop_handler(&dom_namespace_node_prop_handlers, "isConnected", sizeof("isConnected")-1, dom_node_is_connected_read, NULL);
|
||||
dom_register_prop_handler(&dom_namespace_node_prop_handlers, "ownerDocument", sizeof("ownerDocument")-1, dom_node_owner_document_read, NULL);
|
||||
dom_register_prop_handler(&dom_namespace_node_prop_handlers, "parentNode", sizeof("parentNode")-1, dom_node_parent_node_read, NULL);
|
||||
zend_hash_add_ptr(&classes, dom_namespace_node_class_entry->name, &dom_namespace_node_prop_handlers);
|
||||
|
@ -150,7 +150,9 @@ xmlNodePtr php_dom_create_fake_namespace_decl(xmlNodePtr nodep, xmlNsPtr origina
|
||||
void php_dom_get_content_into_zval(const xmlNode *nodep, zval *target, bool default_is_null);
|
||||
zend_string *dom_node_concatenated_name_helper(size_t name_len, const char *name, size_t prefix_len, const char *prefix);
|
||||
zend_string *dom_node_get_node_name_attribute_or_element(const xmlNode *nodep);
|
||||
bool php_dom_is_node_connected(const xmlNode *node);
|
||||
|
||||
/* parentnode */
|
||||
void dom_parent_node_prepend(dom_object *context, zval *nodes, uint32_t nodesc);
|
||||
void dom_parent_node_append(dom_object *context, zval *nodes, uint32_t nodesc);
|
||||
void dom_parent_node_after(dom_object *context, zval *nodes, uint32_t nodesc);
|
||||
|
@ -326,6 +326,9 @@ class DOMNode
|
||||
/** @readonly */
|
||||
public ?DOMNamedNodeMap $attributes;
|
||||
|
||||
/** @readonly */
|
||||
public bool $isConnected;
|
||||
|
||||
/** @readonly */
|
||||
public ?DOMDocument $ownerDocument;
|
||||
|
||||
@ -419,6 +422,9 @@ class DOMNameSpaceNode
|
||||
/** @readonly */
|
||||
public ?string $namespaceURI;
|
||||
|
||||
/** @readonly */
|
||||
public bool $isConnected;
|
||||
|
||||
/** @readonly */
|
||||
public ?DOMDocument $ownerDocument;
|
||||
|
||||
|
14
ext/dom/php_dom_arginfo.h
generated
14
ext/dom/php_dom_arginfo.h
generated
@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 95dc217251318b625cad5b282b1adbb8eedaf1a5 */
|
||||
* Stub hash: 78e4089fa17aa0faa371917aeb48fa0dfe1819b0 */
|
||||
|
||||
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)
|
||||
@ -1138,6 +1138,12 @@ static zend_class_entry *register_class_DOMNode(void)
|
||||
zend_declare_typed_property(class_entry, property_attributes_name, &property_attributes_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_attributes_class_DOMNamedNodeMap, 0, MAY_BE_NULL));
|
||||
zend_string_release(property_attributes_name);
|
||||
|
||||
zval property_isConnected_default_value;
|
||||
ZVAL_UNDEF(&property_isConnected_default_value);
|
||||
zend_string *property_isConnected_name = zend_string_init("isConnected", sizeof("isConnected") - 1, 1);
|
||||
zend_declare_typed_property(class_entry, property_isConnected_name, &property_isConnected_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL));
|
||||
zend_string_release(property_isConnected_name);
|
||||
|
||||
zval property_ownerDocument_default_value;
|
||||
ZVAL_UNDEF(&property_ownerDocument_default_value);
|
||||
zend_string *property_ownerDocument_name = zend_string_init("ownerDocument", sizeof("ownerDocument") - 1, 1);
|
||||
@ -1222,6 +1228,12 @@ static zend_class_entry *register_class_DOMNameSpaceNode(void)
|
||||
zend_declare_typed_property(class_entry, property_namespaceURI_name, &property_namespaceURI_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL));
|
||||
zend_string_release(property_namespaceURI_name);
|
||||
|
||||
zval property_isConnected_default_value;
|
||||
ZVAL_UNDEF(&property_isConnected_default_value);
|
||||
zend_string *property_isConnected_name = zend_string_init("isConnected", sizeof("isConnected") - 1, 1);
|
||||
zend_declare_typed_property(class_entry, property_isConnected_name, &property_isConnected_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL));
|
||||
zend_string_release(property_isConnected_name);
|
||||
|
||||
zval property_ownerDocument_default_value;
|
||||
ZVAL_UNDEF(&property_ownerDocument_default_value);
|
||||
zend_string *property_ownerDocument_name = zend_string_init("ownerDocument", sizeof("ownerDocument") - 1, 1);
|
||||
|
59
ext/dom/tests/DOMNode_DOMNameSpaceNode_isConnected.phpt
Normal file
59
ext/dom/tests/DOMNode_DOMNameSpaceNode_isConnected.phpt
Normal file
@ -0,0 +1,59 @@
|
||||
--TEST--
|
||||
DOMNode::isConnected and DOMNameSpaceNode::isConnected
|
||||
--EXTENSIONS--
|
||||
dom
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$dom = new DOMDocument();
|
||||
$dom->loadXML('<!DOCTYPE html><html><head/><body/></html>');
|
||||
|
||||
$docElement = $dom->documentElement;
|
||||
$head = $docElement->firstChild;
|
||||
$body = $head->nextSibling;
|
||||
|
||||
echo "--- Created element not connected yet ---\n";
|
||||
|
||||
$p = $dom->createElement('p');
|
||||
var_dump($p->isConnected);
|
||||
|
||||
echo "--- Appending and checking connection isn't broken for parents ---\n";
|
||||
|
||||
$body->appendChild($p);
|
||||
var_dump($body->isConnected);
|
||||
var_dump($p->isConnected);
|
||||
$document = $docElement->parentNode;
|
||||
var_dump($document->isConnected);
|
||||
var_dump($dom->doctype->isConnected);
|
||||
|
||||
echo "--- Indirect removal should set isConnected to false for affected nodes ---\n";
|
||||
|
||||
$body->remove();
|
||||
var_dump($p->isConnected);
|
||||
var_dump($docElement->isConnected);
|
||||
var_dump($body->isConnected);
|
||||
var_dump($head->isConnected);
|
||||
var_dump($dom->doctype->isConnected);
|
||||
|
||||
echo "--- Empty document test ---\n";
|
||||
|
||||
$dom = new DOMDocument();
|
||||
var_dump($dom->isConnected);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
--- Created element not connected yet ---
|
||||
bool(false)
|
||||
--- Appending and checking connection isn't broken for parents ---
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
--- Indirect removal should set isConnected to false for affected nodes ---
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(true)
|
||||
--- Empty document test ---
|
||||
bool(true)
|
@ -30,7 +30,7 @@ foreach ($dataNodes AS $node) {
|
||||
?>
|
||||
--EXPECTF--
|
||||
int(3)
|
||||
object(DOMText)#%d (21) {
|
||||
object(DOMText)#%d (22) {
|
||||
["wholeText"]=>
|
||||
string(3) "
|
||||
"
|
||||
@ -64,6 +64,8 @@ object(DOMText)#%d (21) {
|
||||
NULL
|
||||
["attributes"]=>
|
||||
NULL
|
||||
["isConnected"]=>
|
||||
bool(false)
|
||||
["ownerDocument"]=>
|
||||
string(22) "(object value omitted)"
|
||||
["namespaceURI"]=>
|
||||
@ -78,7 +80,7 @@ object(DOMText)#%d (21) {
|
||||
string(3) "
|
||||
"
|
||||
}
|
||||
object(DOMElement)#7 (25) {
|
||||
object(DOMElement)#7 (26) {
|
||||
["schemaTypeInfo"]=>
|
||||
NULL
|
||||
["tagName"]=>
|
||||
@ -121,6 +123,8 @@ object(DOMElement)#7 (25) {
|
||||
NULL
|
||||
["attributes"]=>
|
||||
string(22) "(object value omitted)"
|
||||
["isConnected"]=>
|
||||
bool(false)
|
||||
["ownerDocument"]=>
|
||||
string(22) "(object value omitted)"
|
||||
["namespaceURI"]=>
|
||||
@ -138,7 +142,7 @@ object(DOMElement)#7 (25) {
|
||||
Value C
|
||||
"
|
||||
}
|
||||
object(DOMText)#%d (21) {
|
||||
object(DOMText)#%d (22) {
|
||||
["wholeText"]=>
|
||||
string(1) "
|
||||
"
|
||||
@ -172,6 +176,8 @@ object(DOMText)#%d (21) {
|
||||
NULL
|
||||
["attributes"]=>
|
||||
NULL
|
||||
["isConnected"]=>
|
||||
bool(false)
|
||||
["ownerDocument"]=>
|
||||
string(22) "(object value omitted)"
|
||||
["namespaceURI"]=>
|
||||
|
@ -57,6 +57,7 @@ DOMNameSpaceNode Object
|
||||
[prefix] =>
|
||||
[localName] => xmlns
|
||||
[namespaceURI] => http://www.sitemaps.org/schemas/sitemap/0.9
|
||||
[isConnected] => 1
|
||||
[ownerDocument] => (object value omitted)
|
||||
[parentNode] => (object value omitted)
|
||||
)
|
||||
@ -73,6 +74,7 @@ DOMNameSpaceNode Object
|
||||
[prefix] => xsi
|
||||
[localName] => xsi
|
||||
[namespaceURI] => fooooooooooooooooooooo
|
||||
[isConnected] => 1
|
||||
[ownerDocument] => (object value omitted)
|
||||
[parentNode] => (object value omitted)
|
||||
)
|
||||
|
@ -13,7 +13,7 @@ var_dump($attr);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
object(DOMNameSpaceNode)#3 (8) {
|
||||
object(DOMNameSpaceNode)#3 (9) {
|
||||
["nodeName"]=>
|
||||
string(5) "xmlns"
|
||||
["nodeValue"]=>
|
||||
@ -26,6 +26,8 @@ object(DOMNameSpaceNode)#3 (8) {
|
||||
string(5) "xmlns"
|
||||
["namespaceURI"]=>
|
||||
string(19) "http://php.net/test"
|
||||
["isConnected"]=>
|
||||
bool(true)
|
||||
["ownerDocument"]=>
|
||||
string(22) "(object value omitted)"
|
||||
["parentNode"]=>
|
||||
|
@ -21,7 +21,7 @@ var_dump($target);
|
||||
?>
|
||||
--EXPECTF--
|
||||
<a>barfoobaz<last/></a>
|
||||
object(DOMElement)#3 (25) {
|
||||
object(DOMElement)#3 (26) {
|
||||
["schemaTypeInfo"]=>
|
||||
NULL
|
||||
["tagName"]=>
|
||||
@ -60,6 +60,8 @@ object(DOMElement)#3 (25) {
|
||||
NULL
|
||||
["attributes"]=>
|
||||
string(22) "(object value omitted)"
|
||||
["isConnected"]=>
|
||||
bool(true)
|
||||
["ownerDocument"]=>
|
||||
string(22) "(object value omitted)"
|
||||
["namespaceURI"]=>
|
||||
@ -74,7 +76,7 @@ object(DOMElement)#3 (25) {
|
||||
string(0) ""
|
||||
}
|
||||
<a><last/>barfoobaz</a>
|
||||
object(DOMElement)#2 (25) {
|
||||
object(DOMElement)#2 (26) {
|
||||
["schemaTypeInfo"]=>
|
||||
NULL
|
||||
["tagName"]=>
|
||||
@ -113,6 +115,8 @@ object(DOMElement)#2 (25) {
|
||||
string(22) "(object value omitted)"
|
||||
["attributes"]=>
|
||||
string(22) "(object value omitted)"
|
||||
["isConnected"]=>
|
||||
bool(true)
|
||||
["ownerDocument"]=>
|
||||
string(22) "(object value omitted)"
|
||||
["namespaceURI"]=>
|
||||
|
@ -44,7 +44,7 @@ var_dump($barClone->parentNode);
|
||||
?>
|
||||
--EXPECT--
|
||||
-- Clone DOMNameSpaceNode --
|
||||
object(DOMNameSpaceNode)#3 (8) {
|
||||
object(DOMNameSpaceNode)#3 (9) {
|
||||
["nodeName"]=>
|
||||
string(5) "xmlns"
|
||||
["nodeValue"]=>
|
||||
@ -57,6 +57,8 @@ object(DOMNameSpaceNode)#3 (8) {
|
||||
string(5) "xmlns"
|
||||
["namespaceURI"]=>
|
||||
string(19) "http://php.net/test"
|
||||
["isConnected"]=>
|
||||
bool(true)
|
||||
["ownerDocument"]=>
|
||||
string(22) "(object value omitted)"
|
||||
["parentNode"]=>
|
||||
|
@ -54,6 +54,7 @@ DOMDocument Object
|
||||
[previousSibling] =>
|
||||
[nextSibling] =>
|
||||
[attributes] =>
|
||||
[isConnected] => 1
|
||||
[ownerDocument] =>
|
||||
[namespaceURI] =>
|
||||
[prefix] =>
|
||||
|
@ -17,7 +17,7 @@ var_dump($nodes->item(0));
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
object(DOMNameSpaceNode)#4 (8) {
|
||||
object(DOMNameSpaceNode)#4 (9) {
|
||||
["nodeName"]=>
|
||||
string(9) "xmlns:xml"
|
||||
["nodeValue"]=>
|
||||
@ -30,6 +30,8 @@ object(DOMNameSpaceNode)#4 (8) {
|
||||
string(3) "xml"
|
||||
["namespaceURI"]=>
|
||||
string(36) "http://www.w3.org/XML/1998/namespace"
|
||||
["isConnected"]=>
|
||||
bool(true)
|
||||
["ownerDocument"]=>
|
||||
string(22) "(object value omitted)"
|
||||
["parentNode"]=>
|
||||
|
Loading…
Reference in New Issue
Block a user