Skip to content

Commit d04f48b

Browse files
committed
Implement DOMNode::parentElement and DOMNameSpaceNode::parentElement
ref: https://dom.spec.whatwg.org/#parent-element Closes GH-11679.
1 parent d38cc9b commit d04f48b

15 files changed

+138
-21
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ PHP NEWS
2626
. Added DOMElement::className and DOMElement::id. (nielsdos)
2727
. Added DOMParentNode::replaceChildren(). (nielsdos)
2828
. Added DOMNode::isConnected and DOMNameSpaceNode::isConnected. (nielsdos)
29+
. Added DOMNode::parentElement and DOMNameSpaceNode::parentElement.
30+
(nielsdos)
2931

3032
- FPM:
3133
. Added warning to log when fpm socket was not registered on the expected

UPGRADING

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ PHP 8.3 UPGRADE NOTES
269269
libxml2.
270270
. Added DOMParentNode::replaceChildren().
271271
. Added DOMNode::isConnected and DOMNameSpaceNode::isConnected.
272+
. Added DOMNode::parentElement and DOMNameSpaceNode::parentElement.
272273

273274
- JSON:
274275
. Added json_validate(), which returns whether the json is valid for

ext/dom/dom_properties.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ int dom_node_node_value_read(dom_object *obj, zval *retval);
9999
int dom_node_node_value_write(dom_object *obj, zval *newval);
100100
int dom_node_node_type_read(dom_object *obj, zval *retval);
101101
int dom_node_parent_node_read(dom_object *obj, zval *retval);
102+
zend_result dom_node_parent_element_read(dom_object *obj, zval *retval);
102103
int dom_node_child_nodes_read(dom_object *obj, zval *retval);
103104
int dom_node_first_child_read(dom_object *obj, zval *retval);
104105
int dom_node_last_child_read(dom_object *obj, zval *retval);

ext/dom/node.c

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -237,24 +237,17 @@ int dom_node_node_type_read(dom_object *obj, zval *retval)
237237

238238
/* }}} */
239239

240-
/* {{{ parentNode DomNode
241-
readonly=yes
242-
URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1060184317
243-
Since:
244-
*/
245-
int dom_node_parent_node_read(dom_object *obj, zval *retval)
240+
static zend_result dom_node_parent_get(dom_object *obj, zval *retval, bool only_element)
246241
{
247-
xmlNode *nodep, *nodeparent;
248-
249-
nodep = dom_object_get_node(obj);
242+
xmlNodePtr nodep = dom_object_get_node(obj);
250243

251244
if (nodep == NULL) {
252245
php_dom_throw_error(INVALID_STATE_ERR, 1);
253246
return FAILURE;
254247
}
255248

256-
nodeparent = nodep->parent;
257-
if (!nodeparent) {
249+
xmlNodePtr nodeparent = nodep->parent;
250+
if (!nodeparent || (only_element && nodeparent->type != XML_ELEMENT_NODE)) {
258251
ZVAL_NULL(retval);
259252
return SUCCESS;
260253
}
@@ -263,6 +256,28 @@ int dom_node_parent_node_read(dom_object *obj, zval *retval)
263256
return SUCCESS;
264257
}
265258

259+
/* {{{ parentNode ?DomNode
260+
readonly=yes
261+
URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1060184317
262+
Since:
263+
*/
264+
int dom_node_parent_node_read(dom_object *obj, zval *retval)
265+
{
266+
return dom_node_parent_get(obj, retval, false);
267+
}
268+
269+
/* }}} */
270+
271+
/* {{{ parentElement ?DomElement
272+
readonly=yes
273+
URL: https://dom.spec.whatwg.org/#parent-element
274+
Since:
275+
*/
276+
zend_result dom_node_parent_element_read(dom_object *obj, zval *retval)
277+
{
278+
return dom_node_parent_get(obj, retval, true);
279+
}
280+
266281
/* }}} */
267282

268283
/* {{{ childNodes DomNodeList

ext/dom/php_dom.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,7 @@ PHP_MINIT_FUNCTION(dom)
636636
dom_register_prop_handler(&dom_node_prop_handlers, "nodeValue", sizeof("nodeValue")-1, dom_node_node_value_read, dom_node_node_value_write);
637637
dom_register_prop_handler(&dom_node_prop_handlers, "nodeType", sizeof("nodeType")-1, dom_node_node_type_read, NULL);
638638
dom_register_prop_handler(&dom_node_prop_handlers, "parentNode", sizeof("parentNode")-1, dom_node_parent_node_read, NULL);
639+
dom_register_prop_handler(&dom_node_prop_handlers, "parentElement", sizeof("parentElement")-1, dom_node_parent_element_read, NULL);
639640
dom_register_prop_handler(&dom_node_prop_handlers, "childNodes", sizeof("childNodes")-1, dom_node_child_nodes_read, NULL);
640641
dom_register_prop_handler(&dom_node_prop_handlers, "firstChild", sizeof("firstChild")-1, dom_node_first_child_read, NULL);
641642
dom_register_prop_handler(&dom_node_prop_handlers, "lastChild", sizeof("lastChild")-1, dom_node_last_child_read, NULL);
@@ -664,6 +665,7 @@ PHP_MINIT_FUNCTION(dom)
664665
dom_register_prop_handler(&dom_namespace_node_prop_handlers, "isConnected", sizeof("isConnected")-1, dom_node_is_connected_read, NULL);
665666
dom_register_prop_handler(&dom_namespace_node_prop_handlers, "ownerDocument", sizeof("ownerDocument")-1, dom_node_owner_document_read, NULL);
666667
dom_register_prop_handler(&dom_namespace_node_prop_handlers, "parentNode", sizeof("parentNode")-1, dom_node_parent_node_read, NULL);
668+
dom_register_prop_handler(&dom_namespace_node_prop_handlers, "parentElement", sizeof("parentElement")-1, dom_node_parent_element_read, NULL);
667669
zend_hash_add_ptr(&classes, dom_namespace_node_class_entry->name, &dom_namespace_node_prop_handlers);
668670

669671
dom_documentfragment_class_entry = register_class_DOMDocumentFragment(dom_node_class_entry, dom_parentnode_class_entry);

ext/dom/php_dom.stub.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,9 @@ class DOMNode
308308
/** @readonly */
309309
public ?DOMNode $parentNode;
310310

311+
/** @readonly */
312+
public ?DOMElement $parentElement;
313+
311314
/** @readonly */
312315
public DOMNodeList $childNodes;
313316

@@ -430,6 +433,9 @@ class DOMNameSpaceNode
430433

431434
/** @readonly */
432435
public ?DOMNode $parentNode;
436+
437+
/** @readonly */
438+
public ?DOMElement $parentElement;
433439
}
434440

435441
class DOMImplementation

ext/dom/php_dom_arginfo.h

Lines changed: 15 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
--TEST--
2+
DOMNode::parentElement and DOMNameSpaceNode::parentElement
3+
--EXTENSIONS--
4+
dom
5+
--FILE--
6+
<?php
7+
8+
$dom = new DOMDocument();
9+
$dom->loadXML(<<<XML
10+
<!DOCTYPE HTML>
11+
<html>
12+
<body/>
13+
</html>
14+
XML);
15+
16+
echo "--- body test ---\n";
17+
18+
$body = $dom->documentElement->firstElementChild;
19+
var_dump($body->parentNode->localName);
20+
var_dump($body->parentElement->localName);
21+
22+
echo "--- document test ---\n";
23+
24+
var_dump(get_class($dom->documentElement->parentNode));
25+
var_dump($dom->documentElement->parentElement);
26+
27+
var_dump(get_class($dom->doctype->parentNode));
28+
var_dump($dom->doctype->parentElement);
29+
30+
echo "--- fragment test ---\n";
31+
32+
$fragment = $dom->createDocumentFragment();
33+
$p = $fragment->appendChild($dom->createElement('p'));
34+
35+
var_dump(get_class($p->parentNode));
36+
var_dump($p->parentElement);
37+
38+
$body->appendChild($fragment);
39+
40+
var_dump($p->parentNode->localName);
41+
var_dump($p->parentElement->localName);
42+
43+
?>
44+
--EXPECT--
45+
--- body test ---
46+
string(4) "html"
47+
string(4) "html"
48+
--- document test ---
49+
string(11) "DOMDocument"
50+
NULL
51+
string(11) "DOMDocument"
52+
NULL
53+
--- fragment test ---
54+
string(19) "DOMDocumentFragment"
55+
NULL
56+
string(4) "body"
57+
string(4) "body"

ext/dom/tests/bug69846.phpt

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ foreach ($dataNodes AS $node) {
2828
}
2929

3030
?>
31-
--EXPECTF--
31+
--EXPECT--
3232
int(3)
33-
object(DOMText)#%d (22) {
33+
object(DOMText)#7 (23) {
3434
["wholeText"]=>
3535
string(3) "
3636
"
@@ -52,6 +52,8 @@ object(DOMText)#%d (22) {
5252
int(3)
5353
["parentNode"]=>
5454
NULL
55+
["parentElement"]=>
56+
NULL
5557
["childNodes"]=>
5658
string(22) "(object value omitted)"
5759
["firstChild"]=>
@@ -80,7 +82,7 @@ object(DOMText)#%d (22) {
8082
string(3) "
8183
"
8284
}
83-
object(DOMElement)#7 (26) {
85+
object(DOMElement)#7 (27) {
8486
["schemaTypeInfo"]=>
8587
NULL
8688
["tagName"]=>
@@ -111,6 +113,8 @@ object(DOMElement)#7 (26) {
111113
int(1)
112114
["parentNode"]=>
113115
NULL
116+
["parentElement"]=>
117+
NULL
114118
["childNodes"]=>
115119
string(22) "(object value omitted)"
116120
["firstChild"]=>
@@ -142,7 +146,7 @@ object(DOMElement)#7 (26) {
142146
Value C
143147
"
144148
}
145-
object(DOMText)#%d (22) {
149+
object(DOMText)#7 (23) {
146150
["wholeText"]=>
147151
string(1) "
148152
"
@@ -164,6 +168,8 @@ object(DOMText)#%d (22) {
164168
int(3)
165169
["parentNode"]=>
166170
NULL
171+
["parentElement"]=>
172+
NULL
167173
["childNodes"]=>
168174
string(22) "(object value omitted)"
169175
["firstChild"]=>

ext/dom/tests/bug70359.phpt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ DOMNameSpaceNode Object
6060
[isConnected] => 1
6161
[ownerDocument] => (object value omitted)
6262
[parentNode] => (object value omitted)
63+
[parentElement] => (object value omitted)
6364
)
6465
-- Test with parent and non-ns attribute --
6566
int(2)
@@ -77,5 +78,6 @@ DOMNameSpaceNode Object
7778
[isConnected] => 1
7879
[ownerDocument] => (object value omitted)
7980
[parentNode] => (object value omitted)
81+
[parentElement] => (object value omitted)
8082
)
8183
string(3) "url"

ext/dom/tests/bug78577.phpt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ var_dump($attr);
1313

1414
?>
1515
--EXPECT--
16-
object(DOMNameSpaceNode)#3 (9) {
16+
object(DOMNameSpaceNode)#3 (10) {
1717
["nodeName"]=>
1818
string(5) "xmlns"
1919
["nodeValue"]=>
@@ -32,4 +32,6 @@ object(DOMNameSpaceNode)#3 (9) {
3232
string(22) "(object value omitted)"
3333
["parentNode"]=>
3434
string(22) "(object value omitted)"
35+
["parentElement"]=>
36+
string(22) "(object value omitted)"
3537
}

ext/dom/tests/bug80602_3.phpt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ var_dump($target);
2121
?>
2222
--EXPECTF--
2323
<a>barfoobaz<last/></a>
24-
object(DOMElement)#3 (26) {
24+
object(DOMElement)#3 (27) {
2525
["schemaTypeInfo"]=>
2626
NULL
2727
["tagName"]=>
@@ -48,6 +48,8 @@ object(DOMElement)#3 (26) {
4848
int(1)
4949
["parentNode"]=>
5050
string(22) "(object value omitted)"
51+
["parentElement"]=>
52+
string(22) "(object value omitted)"
5153
["childNodes"]=>
5254
string(22) "(object value omitted)"
5355
["firstChild"]=>
@@ -76,7 +78,7 @@ object(DOMElement)#3 (26) {
7678
string(0) ""
7779
}
7880
<a><last/>barfoobaz</a>
79-
object(DOMElement)#2 (26) {
81+
object(DOMElement)#2 (27) {
8082
["schemaTypeInfo"]=>
8183
NULL
8284
["tagName"]=>
@@ -103,6 +105,8 @@ object(DOMElement)#2 (26) {
103105
int(1)
104106
["parentNode"]=>
105107
string(22) "(object value omitted)"
108+
["parentElement"]=>
109+
string(22) "(object value omitted)"
106110
["childNodes"]=>
107111
string(22) "(object value omitted)"
108112
["firstChild"]=>

ext/dom/tests/clone_nodes.phpt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ var_dump($barClone->parentNode);
4444
?>
4545
--EXPECT--
4646
-- Clone DOMNameSpaceNode --
47-
object(DOMNameSpaceNode)#3 (9) {
47+
object(DOMNameSpaceNode)#3 (10) {
4848
["nodeName"]=>
4949
string(5) "xmlns"
5050
["nodeValue"]=>
@@ -63,6 +63,8 @@ object(DOMNameSpaceNode)#3 (9) {
6363
string(22) "(object value omitted)"
6464
["parentNode"]=>
6565
string(22) "(object value omitted)"
66+
["parentElement"]=>
67+
string(22) "(object value omitted)"
6668
}
6769
string(19) "http://php.net/test"
6870
string(3) "foo"

ext/dom/tests/domobject_debug_handler.phpt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ DOMDocument Object
4848
[nodeValue] =>
4949
[nodeType] => 9
5050
[parentNode] =>
51+
[parentElement] =>
5152
[childNodes] => (object value omitted)
5253
[firstChild] => (object value omitted)
5354
[lastChild] => (object value omitted)

ext/dom/tests/xpath_domnamespacenode.phpt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ var_dump($nodes->item(0));
1717

1818
?>
1919
--EXPECT--
20-
object(DOMNameSpaceNode)#4 (9) {
20+
object(DOMNameSpaceNode)#4 (10) {
2121
["nodeName"]=>
2222
string(9) "xmlns:xml"
2323
["nodeValue"]=>
@@ -36,4 +36,6 @@ object(DOMNameSpaceNode)#4 (9) {
3636
string(22) "(object value omitted)"
3737
["parentNode"]=>
3838
string(22) "(object value omitted)"
39+
["parentElement"]=>
40+
string(22) "(object value omitted)"
3941
}

0 commit comments

Comments
 (0)