Skip to content

Commit ea794e9

Browse files
committed
1 parent 2aaa799 commit ea794e9

File tree

6 files changed

+160
-1
lines changed

6 files changed

+160
-1
lines changed

NEWS

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ PHP NEWS
1414
. Added zend_call_stack_get implementation for OpenBSD. (David Carlier)
1515
. Fixed oss-fuzz #60411 (Fix double-compilation of arrow-functions). (ilutov)
1616

17+
- DOM:
18+
. Added DOMNode::contains() and DOMNameSpaceNode::contains(). (nielsdos)
19+
1720
- Intl:
1821
. Fix memory leak in MessageFormatter::format() on failure. (Girgias)
1922

UPGRADING

+3
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,9 @@ PHP 8.3 UPGRADE NOTES
238238
6. New Functions
239239
========================================
240240

241+
- DOM:
242+
. Added DOMNode::contains() and DOMNameSpaceNode::contains().
243+
241244
- JSON:
242245
. Added json_validate(), which returns whether the json is valid for
243246
the given $depth and $options.

ext/dom/node.c

+36
Original file line numberDiff line numberDiff line change
@@ -1782,4 +1782,40 @@ PHP_METHOD(DOMNode, getLineNo)
17821782
}
17831783
/* }}} */
17841784

1785+
/* {{{ URL: https://dom.spec.whatwg.org/#dom-node-contains
1786+
Since:
1787+
*/
1788+
PHP_METHOD(DOMNode, contains)
1789+
{
1790+
zval *other, *id;
1791+
xmlNodePtr otherp, thisp;
1792+
dom_object *unused_intern;
1793+
1794+
ZEND_PARSE_PARAMETERS_START(1, 1)
1795+
Z_PARAM_OBJECT_OR_NULL(other)
1796+
ZEND_PARSE_PARAMETERS_END();
1797+
1798+
if (other == NULL) {
1799+
RETURN_FALSE;
1800+
}
1801+
1802+
if (UNEXPECTED(!instanceof_function(Z_OBJCE_P(other), dom_node_class_entry) && !instanceof_function(Z_OBJCE_P(other), dom_namespace_node_class_entry))) {
1803+
zend_argument_type_error(1, "must be of type DOMNode|DOMNameSpaceNode|null, %s given", zend_zval_value_name(other));
1804+
RETURN_THROWS();
1805+
}
1806+
1807+
DOM_GET_OBJ(otherp, other, xmlNodePtr, unused_intern);
1808+
DOM_GET_THIS_OBJ(thisp, id, xmlNodePtr, unused_intern);
1809+
1810+
do {
1811+
if (otherp == thisp) {
1812+
RETURN_TRUE;
1813+
}
1814+
otherp = otherp->parent;
1815+
} while (otherp);
1816+
1817+
RETURN_FALSE;
1818+
}
1819+
/* }}} */
1820+
17851821
#endif

ext/dom/php_dom.stub.php

+2
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,8 @@ public function removeChild(DOMNode $child) {}
389389

390390
/** @return DOMNode|false */
391391
public function replaceChild(DOMNode $node, DOMNode $child) {}
392+
393+
public function contains(DOMNode|DOMNameSpaceNode|null $other): bool {}
392394
}
393395

394396
/** @not-serializable */

ext/dom/php_dom_arginfo.h

+7-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/dom/tests/DOMNode_contains.phpt

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
--TEST--
2+
DOMNode::contains()
3+
--EXTENSIONS--
4+
dom
5+
--FILE--
6+
<?php
7+
8+
$dom = new DOMDocument();
9+
$dom->loadXML(<<<XML
10+
<!DOCTYPE HTML>
11+
<html xmlns:test="some:ns">
12+
<head>
13+
<title>my title</title>
14+
</head>
15+
<body>
16+
<main>
17+
<p>Hello, world!</p>
18+
<p>Second paragraph</p>
19+
<div><p>container</p></div>
20+
<!-- comment -->
21+
</main>
22+
</body>
23+
</html>
24+
XML);
25+
26+
$xpath = new DOMXPath($dom);
27+
$head = $xpath->query("//head")[0];
28+
$main = $xpath->query("//main")[0];
29+
$div = $xpath->query("//div")[0];
30+
31+
echo "--- False edge cases ---\n";
32+
33+
var_dump($dom->documentElement->contains(null));
34+
35+
try {
36+
var_dump($dom->contains(new stdClass));
37+
} catch (TypeError $e) {
38+
echo $e->getMessage(), "\n";
39+
}
40+
41+
echo "--- True cases ---\n";
42+
var_dump($dom->documentElement->contains($head));
43+
var_dump($dom->documentElement->contains($main));
44+
var_dump($dom->contains($dom));
45+
var_dump($main->contains($main));
46+
var_dump($div->contains($div));
47+
var_dump($main->contains($div));
48+
var_dump($main->contains($main->firstElementChild));
49+
var_dump($main->contains($div->firstElementChild));
50+
var_dump($div->contains($div->firstElementChild));
51+
var_dump($main->contains($main->firstElementChild->firstChild));
52+
var_dump($dom->contains($dom->doctype));
53+
var_dump($dom->contains($dom->doctype));
54+
var_dump($dom->contains($dom->documentElement->getAttributeNode('xmlns:test')));
55+
var_dump($dom->contains($main->lastChild));
56+
57+
echo "--- False cases ---\n";
58+
var_dump($main->firstElementChild->contains($main));
59+
var_dump($main->contains($head));
60+
var_dump($div->contains($main));
61+
var_dump($main->contains($head->firstElementChild));
62+
var_dump($div->contains($main->firstElementChild));
63+
var_dump($div->contains($main->firstElementChild->nextElementSibling));
64+
var_dump($div->contains($main->lastChild));
65+
66+
echo "--- False, create element case ---\n";
67+
68+
$newElement = $dom->createElement('x');
69+
var_dump($dom->documentElement->contains($newElement));
70+
71+
echo "--- Removal case ---\n";
72+
73+
$main->remove();
74+
var_dump($main->contains($main));
75+
var_dump($dom->contains($main));
76+
77+
?>
78+
--EXPECT--
79+
--- False edge cases ---
80+
bool(false)
81+
DOMNode::contains(): Argument #1 ($other) must be of type DOMNode|DOMNameSpaceNode|null, stdClass given
82+
--- True cases ---
83+
bool(true)
84+
bool(true)
85+
bool(true)
86+
bool(true)
87+
bool(true)
88+
bool(true)
89+
bool(true)
90+
bool(true)
91+
bool(true)
92+
bool(true)
93+
bool(true)
94+
bool(true)
95+
bool(true)
96+
bool(true)
97+
--- False cases ---
98+
bool(false)
99+
bool(false)
100+
bool(false)
101+
bool(false)
102+
bool(false)
103+
bool(false)
104+
bool(false)
105+
--- False, create element case ---
106+
bool(false)
107+
--- Removal case ---
108+
bool(true)
109+
bool(false)

0 commit comments

Comments
 (0)