Skip to content

Commit 5acd86d

Browse files
committed
[RFC] Implement new DOM Living Standard APIs in ext/dom
1 parent 87bc994 commit 5acd86d

35 files changed

+1565
-41
lines changed

ext/dom/characterdata.c

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ const zend_function_entry php_dom_characterdata_class_functions[] = {
3737
PHP_ME(domcharacterdata, insertData, arginfo_class_DOMCharacterData_insertData, ZEND_ACC_PUBLIC)
3838
PHP_ME(domcharacterdata, deleteData, arginfo_class_DOMCharacterData_deleteData, ZEND_ACC_PUBLIC)
3939
PHP_ME(domcharacterdata, replaceData, arginfo_class_DOMCharacterData_replaceData, ZEND_ACC_PUBLIC)
40+
PHP_ME(domcharacterdata, remove, arginfo_class_DOMChildNode_remove, ZEND_ACC_PUBLIC)
41+
PHP_ME(domcharacterdata, after, arginfo_class_DOMChildNode_after, ZEND_ACC_PUBLIC)
42+
PHP_ME(domcharacterdata, before, arginfo_class_DOMChildNode_before, ZEND_ACC_PUBLIC)
43+
PHP_ME(domcharacterdata, replaceWith, arginfo_class_DOMChildNode_replaceWith, ZEND_ACC_PUBLIC)
4044
PHP_FE_END
4145
};
4246

@@ -361,4 +365,104 @@ PHP_METHOD(domcharacterdata, replaceData)
361365
}
362366
/* }}} end dom_characterdata_replace_data */
363367

368+
PHP_METHOD(domcharacterdata, remove)
369+
{
370+
zval *id = ZEND_THIS;
371+
xmlNodePtr children, child;
372+
dom_object *intern;
373+
int stricterror;
374+
375+
if (zend_parse_parameters_none() == FAILURE) {
376+
RETURN_THROWS();
377+
}
378+
379+
DOM_GET_OBJ(child, id, xmlNodePtr, intern);
380+
381+
if (dom_node_children_valid(child) == FAILURE) {
382+
RETURN_NULL();
383+
}
384+
385+
stricterror = dom_get_strict_error(intern->document);
386+
387+
if (dom_node_is_read_only(child) == SUCCESS ||
388+
(child->parent != NULL && dom_node_is_read_only(child->parent) == SUCCESS)) {
389+
php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror);
390+
RETURN_NULL();
391+
}
392+
393+
if (!child->parent) {
394+
php_dom_throw_error(NOT_FOUND_ERR, stricterror);
395+
RETURN_NULL();
396+
}
397+
398+
children = child->parent->children;
399+
if (!children) {
400+
php_dom_throw_error(NOT_FOUND_ERR, stricterror);
401+
RETURN_NULL();
402+
}
403+
404+
while (children) {
405+
if (children == child) {
406+
xmlUnlinkNode(child);
407+
RETURN_NULL();
408+
}
409+
children = children->next;
410+
}
411+
412+
php_dom_throw_error(NOT_FOUND_ERR, stricterror);
413+
RETURN_NULL();
414+
}
415+
416+
PHP_METHOD(domcharacterdata, after)
417+
{
418+
int argc;
419+
zval *args, *id;
420+
dom_object *intern;
421+
xmlNode *context;
422+
423+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
424+
RETURN_THROWS();
425+
}
426+
427+
id = ZEND_THIS;
428+
DOM_GET_OBJ(context, id, xmlNodePtr, intern);
429+
430+
dom_parent_node_after(intern, args, argc);
431+
}
432+
433+
PHP_METHOD(domcharacterdata, before)
434+
{
435+
int argc;
436+
zval *args, *id;
437+
dom_object *intern;
438+
xmlNode *context;
439+
440+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
441+
RETURN_THROWS();
442+
}
443+
444+
id = ZEND_THIS;
445+
DOM_GET_OBJ(context, id, xmlNodePtr, intern);
446+
447+
dom_parent_node_before(intern, args, argc);
448+
}
449+
450+
PHP_METHOD(domcharacterdata, replaceWith)
451+
{
452+
int argc;
453+
zval *args, *id;
454+
dom_object *intern;
455+
xmlNode *context;
456+
457+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
458+
RETURN_THROWS();
459+
}
460+
461+
id = ZEND_THIS;
462+
DOM_GET_OBJ(context, id, xmlNodePtr, intern);
463+
464+
dom_parent_node_after(intern, args, argc);
465+
dom_child_node_remove(intern);
466+
}
467+
364468
#endif

ext/dom/config.m4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ if test "$PHP_DOM" != "no"; then
1313
PHP_SETUP_LIBXML(DOM_SHARED_LIBADD, [
1414
AC_DEFINE(HAVE_DOM,1,[ ])
1515
PHP_NEW_EXTENSION(dom, [php_dom.c attr.c document.c \
16-
domexception.c \
16+
domexception.c parentnode.c \
1717
processinginstruction.c cdatasection.c \
1818
documentfragment.c domimplementation.c \
1919
element.c node.c characterdata.c \

ext/dom/config.w32

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ if (PHP_DOM == "yes") {
88
CHECK_HEADER_ADD_INCLUDE("libxml/parser.h", "CFLAGS_DOM", PHP_PHP_BUILD + "\\include\\libxml2")
99
) {
1010
EXTENSION("dom", "php_dom.c attr.c document.c \
11-
domexception.c processinginstruction.c \
11+
domexception.c parentnode.c processinginstruction.c \
1212
cdatasection.c documentfragment.c domimplementation.c element.c \
1313
node.c characterdata.c documenttype.c \
1414
entity.c nodelist.c text.c comment.c \

ext/dom/document.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ const zend_function_entry php_dom_document_class_functions[] = { /* {{{ */
8282
PHP_ME(domdocument, relaxNGValidateSource, arginfo_class_DOMDocument_relaxNGValidateSource, ZEND_ACC_PUBLIC)
8383
#endif
8484
PHP_ME(domdocument, registerNodeClass, arginfo_class_DOMDocument_registerNodeClass, ZEND_ACC_PUBLIC)
85+
PHP_ME(domdocument, append, arginfo_class_DOMParentNode_append, ZEND_ACC_PUBLIC)
86+
PHP_ME(domdocument, prepend, arginfo_class_DOMParentNode_prepend, ZEND_ACC_PUBLIC)
8587
PHP_FE_END
8688
};
8789
/* }}} */
@@ -2128,4 +2130,48 @@ PHP_METHOD(domdocument, registerNodeClass)
21282130
}
21292131
/* }}} */
21302132

2133+
/* {{{ proto void domdocument::append(string|DOMNode ...$nodes)
2134+
URL: https://dom.spec.whatwg.org/#dom-parentnode-append
2135+
Since: DOM Living Standard (DOM4)
2136+
*/
2137+
PHP_METHOD(domdocument, append)
2138+
{
2139+
int argc;
2140+
zval *args, *id;
2141+
dom_object *intern;
2142+
xmlNode *context;
2143+
2144+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
2145+
RETURN_THROWS();
2146+
}
2147+
2148+
id = ZEND_THIS;
2149+
DOM_GET_OBJ(context, id, xmlNodePtr, intern);
2150+
2151+
dom_parent_node_append(intern, args, argc);
2152+
}
2153+
/* }}} */
2154+
2155+
/* {{{ proto void domdocument::prepend(string|DOMNode ...$nodes)
2156+
URL: https://dom.spec.whatwg.org/#dom-parentnode-prepend
2157+
Since: DOM Living Standard (DOM4)
2158+
*/
2159+
PHP_METHOD(domdocument, prepend)
2160+
{
2161+
int argc;
2162+
zval *args, *id;
2163+
dom_object *intern;
2164+
xmlNode *context;
2165+
2166+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
2167+
RETURN_THROWS();
2168+
}
2169+
2170+
id = ZEND_THIS;
2171+
DOM_GET_OBJ(context, id, xmlNodePtr, intern);
2172+
2173+
dom_parent_node_prepend(intern, args, argc);
2174+
}
2175+
/* }}} */
2176+
21312177
#endif /* HAVE_LIBXML && HAVE_DOM */

ext/dom/documentfragment.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
const zend_function_entry php_dom_documentfragment_class_functions[] = {
3535
PHP_ME(domdocumentfragment, __construct, arginfo_class_DOMDocumentFragment___construct, ZEND_ACC_PUBLIC)
3636
PHP_ME(domdocumentfragment, appendXML, arginfo_class_DOMDocumentFragment_appendXML, ZEND_ACC_PUBLIC)
37+
PHP_ME(domdocumentfragment, append, arginfo_class_DOMParentNode_append, ZEND_ACC_PUBLIC)
38+
PHP_ME(domdocumentfragment, prepend, arginfo_class_DOMParentNode_prepend, ZEND_ACC_PUBLIC)
3739
PHP_FE_END
3840
};
3941

@@ -137,4 +139,48 @@ PHP_METHOD(domdocumentfragment, appendXML) {
137139
}
138140
/* }}} */
139141

142+
/* {{{ proto void domdocumentfragment::append(string|DOMNode ...$nodes)
143+
URL: https://dom.spec.whatwg.org/#dom-parentnode-append
144+
Since: DOM Living Standard (DOM4)
145+
*/
146+
PHP_METHOD(domdocumentfragment, append)
147+
{
148+
int argc;
149+
zval *args, *id;
150+
dom_object *intern;
151+
xmlNode *context;
152+
153+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
154+
RETURN_THROWS();
155+
}
156+
157+
id = ZEND_THIS;
158+
DOM_GET_OBJ(context, id, xmlNodePtr, intern);
159+
160+
dom_parent_node_append(intern, args, argc);
161+
}
162+
/* }}} */
163+
164+
/* {{{ proto void domdocumentfragment::prepend(string|DOMNode ...$nodes)
165+
URL: https://dom.spec.whatwg.org/#dom-parentnode-prepend
166+
Since: DOM Living Standard (DOM4)
167+
*/
168+
PHP_METHOD(domdocumentfragment, prepend)
169+
{
170+
int argc;
171+
zval *args, *id;
172+
dom_object *intern;
173+
xmlNode *context;
174+
175+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
176+
RETURN_THROWS();
177+
}
178+
179+
id = ZEND_THIS;
180+
DOM_GET_OBJ(context, id, xmlNodePtr, intern);
181+
182+
dom_parent_node_prepend(intern, args, argc);
183+
}
184+
/* }}} */
185+
140186
#endif

ext/dom/dom.stub.php

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,28 @@
11
<?php
22

3+
interface DOMChildNode
4+
{
5+
public function remove(): void;
6+
7+
/** @var ...DOMNode|string $nodes */
8+
public function before(... $nodes): void;
9+
10+
/** @var ...DOMNode|string $nodes */
11+
public function after(...$nodes): void;
12+
13+
/** @var ...DOMNode|string $nodes */
14+
public function replaceWith(...$nodes): void;
15+
}
16+
17+
interface DOMParentNode
18+
{
19+
/** @var ...DOMNode|string $nodes */
20+
public function append(...$nodes): void;
21+
22+
/** @var ...DOMNode|string $nodes */
23+
public function prepend(...$nodes): void;
24+
}
25+
326
class DOMNode {
427
/** @return DOMNode|false */
528
public function appendChild(DOMNode $newChild) {}
@@ -63,7 +86,7 @@ class DOMCdataSection {
6386
public function __construct(string $value) {}
6487
}
6588

66-
class DOMCharacterData {
89+
class DOMCharacterData implements DOMChildNode {
6790
/** @return bool */
6891
public function appendData(string $data) {}
6992

@@ -84,7 +107,7 @@ class DOMComment {
84107
public function __construct(string $value = "") {}
85108
}
86109

87-
class DOMDocument {
110+
class DOMDocument implements DOMParentNode {
88111
public function __construct(string $version = "1.0", string $encoding = UNKNOWN) {}
89112

90113
/** @return DOMAttr|false */
@@ -185,14 +208,14 @@ public function xinclude(int $options = 0) {}
185208
public function adoptNode(DOMNode $source) {}
186209
}
187210

188-
class DOMDocumentFragment {
211+
class DOMDocumentFragment implements DOMParentNode {
189212
public function __construct() {}
190213

191214
/** @return bool */
192215
public function appendXML(string $data) {}
193216
}
194217

195-
class DOMElement {
218+
class DOMElement implements DOMParentNode, DOMChildNode {
196219
public function __construct(string $name, ?string $value = null, string $uri = "") {}
197220

198221
/** @return string */

ext/dom/dom_arginfo.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
/* This is a generated file, edit the .stub.php file instead. */
22

3+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_DOMChildNode_remove, 0, 0, IS_VOID, 0)
4+
ZEND_END_ARG_INFO()
5+
6+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_DOMChildNode_before, 0, 0, IS_VOID, 0)
7+
ZEND_ARG_VARIADIC_INFO(0, nodes)
8+
ZEND_END_ARG_INFO()
9+
10+
#define arginfo_class_DOMChildNode_after arginfo_class_DOMChildNode_before
11+
12+
#define arginfo_class_DOMChildNode_replaceWith arginfo_class_DOMChildNode_before
13+
14+
#define arginfo_class_DOMParentNode_append arginfo_class_DOMChildNode_before
15+
16+
#define arginfo_class_DOMParentNode_prepend arginfo_class_DOMChildNode_before
17+
318
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DOMNode_appendChild, 0, 0, 1)
419
ZEND_ARG_OBJ_INFO(0, newChild, DOMNode, 0)
520
ZEND_END_ARG_INFO()

ext/dom/dom_fe.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#define DOM_FE_H
2020

2121
extern const zend_function_entry php_dom_domexception_class_functions[];
22+
extern const zend_function_entry php_dom_parent_node_class_functions[];
23+
extern const zend_function_entry php_dom_child_node_class_functions[];
2224
extern const zend_function_entry php_dom_domimplementation_class_functions[];
2325
extern const zend_function_entry php_dom_documentfragment_class_functions[];
2426
extern const zend_function_entry php_dom_document_class_functions[];
@@ -75,6 +77,8 @@ PHP_METHOD(domimplementation, getFeature);
7577
/* domdocumentfragment methods */
7678
PHP_METHOD(domdocumentfragment, __construct);
7779
PHP_METHOD(domdocumentfragment, appendXML);
80+
PHP_METHOD(domdocumentfragment, append);
81+
PHP_METHOD(domdocumentfragment, prepend);
7882

7983
/* domdocument methods */
8084
PHP_METHOD(domdocument, createElement);
@@ -102,6 +106,8 @@ PHP_METHOD(domdocument, saveXML);
102106
PHP_METHOD(domdocument, validate);
103107
PHP_METHOD(domdocument, xinclude);
104108
PHP_METHOD(domdocument, registerNodeClass);
109+
PHP_METHOD(domdocument, append);
110+
PHP_METHOD(domdocument, prepend);
105111

106112
#if defined(LIBXML_HTML_ENABLED)
107113
PHP_METHOD(domdocument, loadHTML);
@@ -152,6 +158,10 @@ PHP_METHOD(domcharacterdata, appendData);
152158
PHP_METHOD(domcharacterdata, insertData);
153159
PHP_METHOD(domcharacterdata, deleteData);
154160
PHP_METHOD(domcharacterdata, replaceData);
161+
PHP_METHOD(domcharacterdata, remove);
162+
PHP_METHOD(domcharacterdata, after);
163+
PHP_METHOD(domcharacterdata, before);
164+
PHP_METHOD(domcharacterdata, replaceWith);
155165

156166
/* domattr methods */
157167
PHP_METHOD(domattr, isId);
@@ -177,6 +187,12 @@ PHP_METHOD(domelement, setIdAttribute);
177187
PHP_METHOD(domelement, setIdAttributeNS);
178188
PHP_METHOD(domelement, setIdAttributeNode);
179189
PHP_METHOD(domelement, __construct);
190+
PHP_METHOD(domelement, remove);
191+
PHP_METHOD(domelement, after);
192+
PHP_METHOD(domelement, before);
193+
PHP_METHOD(domelement, append);
194+
PHP_METHOD(domelement, prepend);
195+
PHP_METHOD(domelement, replaceWith);
180196

181197
/* domtext methods */
182198
PHP_METHOD(domtext, splitText);

0 commit comments

Comments
 (0)