Skip to content

Add new DOM Living Standard API to ext/dom #4709

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 57 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
a64d792
dom: Let DOMElement implement DOM Level 4 DOMParentNode interface
beberlei Mar 3, 2019
506fd39
[dom] Have DOMDocument implement DOMParentNode.
beberlei Mar 3, 2019
4f3796e
[dom] Add DOMParentNode implementation to DOMDocumentFragment. Fix te…
beberlei Mar 3, 2019
799db74
[dom] Add DOMNode#previousElementSibling and DOMNode#nextElementSibling.
beberlei Mar 3, 2019
865f65f
[dom] DomChildNode#remove interface and DOMElement implementation
beberlei Mar 12, 2019
adce6d1
[dom] fix parameter parsing for DomElement#remove()
beberlei Mar 12, 2019
18d4395
RETURN_NULL as proto is always void.
beberlei Mar 12, 2019
07362cd
Test: DOM Level4 DOMNode::remove()
ThomasWeinert Mar 12, 2019
ca72b19
Test: DOM Level4 DOMNode::before()
ThomasWeinert Mar 17, 2019
33368a0
Test: DOM Level4 DOMNode::after()
ThomasWeinert Mar 17, 2019
6b1d65e
Test: DOM Level4 DOMNode::replaceWith()
ThomasWeinert Mar 17, 2019
46a3248
Test: DOM Level4 DOMParentNode::prepend()
ThomasWeinert Mar 17, 2019
94b7500
Test: DOM Level4 DOMParentNode::append()
ThomasWeinert Mar 17, 2019
fc6c639
Add DOMParentNode::append() for DOMElement supporting strings as vari…
beberlei Mar 20, 2019
c62b8b5
Adopt DoMNode into fragment when passed an object.
beberlei Mar 20, 2019
ece10c6
Refactor converting zval array into dom fragment into function.
beberlei Mar 20, 2019
0670bdd
Add DOMElement::prepend.
beberlei Mar 20, 2019
518583d
Refactor dom_zvals_to_fragment to convert all non DOMNode zvals of an…
beberlei Mar 20, 2019
36f299b
Add prepend/append to DOMParentNode interface and add dummy implement…
beberlei Mar 21, 2019
f03fbae
Add docs to DOMParentNode methods.
beberlei Mar 22, 2019
080ee99
Add code for DOMDocument+DOMDocumentFragment implementations of appen…
beberlei Mar 22, 2019
cb5bffa
Add DOMElement::after() and ::before() stubs.
beberlei Mar 22, 2019
4021b9e
Implement DOMElement::after() and DOMElement::before()
beberlei Mar 22, 2019
7fa76e6
Make DOMCharacterData implements DOMChildNode
beberlei Mar 22, 2019
1b08995
Test: DOM Level4 node adoption and append with attributes
ThomasWeinert Mar 31, 2019
c6f732c
Add namespace reconcile support for append/prepend/after/before.
beberlei Apr 7, 2019
7e6528a
Update tests.
beberlei Apr 7, 2019
3165e36
Prototype on node adoption.
beberlei Apr 8, 2019
553e073
Move previous/nextElementSibling from DOMNode to DOMElement+DOMCharac…
beberlei Sep 15, 2019
8685c14
Add stub for DOMElement#replaceWith and DOMCharacterData#replaceWith.
beberlei Sep 15, 2019
30907dd
Guard against no fragment and throw exception on invalid node types.
beberlei Sep 15, 2019
6fce31e
Similar to DOMNode::appendChild, prevent append/prepend for DOMAttr.
beberlei Sep 15, 2019
4690683
Throw DOMException Hierachy Request Error to be more in line with DOM…
beberlei Sep 15, 2019
1722e0f
Factor out dom_child_node_remove helper function for reuse.
beberlei Sep 15, 2019
565696b
Implement DOMElement::replaceWith, DOMCharacterData::replaceWith.
beberlei Sep 15, 2019
5bbd796
Remove adoptNode prototype as adopting nodes is not implemented and W…
beberlei Sep 16, 2019
81c056e
Merge master into DomLivingStandard.
beberlei Nov 9, 2019
a3f9c0d
Merge origin/master into DomLivingStandard
beberlei Nov 9, 2019
b85b9ec
Add DOMLivingStandard APIs to dom.stub.php
beberlei Nov 9, 2019
0f3b6cd
More tests for wrong document error in parent and child node cases.
beberlei Nov 9, 2019
c4ac9a4
merge master into DomLivingStandard
beberlei Jan 26, 2020
66ea5b1
Expand on append() test
beberlei Jan 26, 2020
7daaf9b
Expand on ::prepend() test.
beberlei Jan 26, 2020
c0741a3
Merge branch 'master' into DomLivingStandard
beberlei Feb 6, 2020
eac2482
Remove trailing whitespaces from Node Content: test output.
beberlei Feb 6, 2020
0fef8ec
Add more things to prepend test.
beberlei Feb 6, 2020
9cf62b6
Apply review comments, improve test output and add more complexity to…
beberlei Feb 6, 2020
d875308
RETURN_THROWS
beberlei Feb 6, 2020
9b79816
Free memory appropriately
beberlei Feb 6, 2020
2031c2b
Bugfix: after/before loosing nodes.
beberlei Feb 6, 2020
1c497bc
Move empty children test into prepend function to avoid duplication.
beberlei Feb 6, 2020
3bc655e
Add test for DOMNode#remove with dangling element causing error.
beberlei Feb 13, 2020
e3f7983
Cleanup tests
beberlei Feb 27, 2020
0372245
Fix stub style
beberlei Feb 27, 2020
363e4f8
Factor out dom_parent_node_assign_parent
beberlei Feb 27, 2020
c686680
Centralize newchild->prev assignment to the end everywhere.
beberlei Feb 27, 2020
7be07e4
Cleanup fragment and parent node assignment.
beberlei Feb 27, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions ext/dom/characterdata.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ const zend_function_entry php_dom_characterdata_class_functions[] = {
PHP_ME(domcharacterdata, insertData, arginfo_class_DOMCharacterData_insertData, ZEND_ACC_PUBLIC)
PHP_ME(domcharacterdata, deleteData, arginfo_class_DOMCharacterData_deleteData, ZEND_ACC_PUBLIC)
PHP_ME(domcharacterdata, replaceData, arginfo_class_DOMCharacterData_replaceData, ZEND_ACC_PUBLIC)
PHP_ME(domcharacterdata, remove, arginfo_class_DOMChildNode_remove, ZEND_ACC_PUBLIC)
PHP_ME(domcharacterdata, after, arginfo_class_DOMChildNode_after, ZEND_ACC_PUBLIC)
PHP_ME(domcharacterdata, before, arginfo_class_DOMChildNode_before, ZEND_ACC_PUBLIC)
PHP_ME(domcharacterdata, replaceWith, arginfo_class_DOMChildNode_replaceWith, ZEND_ACC_PUBLIC)
PHP_FE_END
};

Expand Down Expand Up @@ -361,4 +365,104 @@ PHP_METHOD(domcharacterdata, replaceData)
}
/* }}} end dom_characterdata_replace_data */

PHP_METHOD(domcharacterdata, remove)
{
zval *id = ZEND_THIS;
xmlNodePtr children, child;
dom_object *intern;
int stricterror;

if (zend_parse_parameters_none() == FAILURE) {
RETURN_THROWS();
}

DOM_GET_OBJ(child, id, xmlNodePtr, intern);

if (dom_node_children_valid(child) == FAILURE) {
RETURN_NULL();
}

stricterror = dom_get_strict_error(intern->document);

if (dom_node_is_read_only(child) == SUCCESS ||
(child->parent != NULL && dom_node_is_read_only(child->parent) == SUCCESS)) {
php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror);
RETURN_NULL();
}

if (!child->parent) {
php_dom_throw_error(NOT_FOUND_ERR, stricterror);
RETURN_NULL();
}

children = child->parent->children;
if (!children) {
php_dom_throw_error(NOT_FOUND_ERR, stricterror);
RETURN_NULL();
}

while (children) {
if (children == child) {
xmlUnlinkNode(child);
RETURN_NULL();
}
children = children->next;
}

php_dom_throw_error(NOT_FOUND_ERR, stricterror);
RETURN_NULL();
}

PHP_METHOD(domcharacterdata, after)
{
int argc;
zval *args, *id;
dom_object *intern;
xmlNode *context;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
RETURN_THROWS();
}

id = ZEND_THIS;
DOM_GET_OBJ(context, id, xmlNodePtr, intern);

dom_parent_node_after(intern, args, argc);
}

PHP_METHOD(domcharacterdata, before)
{
int argc;
zval *args, *id;
dom_object *intern;
xmlNode *context;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
RETURN_THROWS();
}

id = ZEND_THIS;
DOM_GET_OBJ(context, id, xmlNodePtr, intern);

dom_parent_node_before(intern, args, argc);
}

PHP_METHOD(domcharacterdata, replaceWith)
{
int argc;
zval *args, *id;
dom_object *intern;
xmlNode *context;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
RETURN_THROWS();
}

id = ZEND_THIS;
DOM_GET_OBJ(context, id, xmlNodePtr, intern);

dom_parent_node_after(intern, args, argc);
dom_child_node_remove(intern);
}

#endif
2 changes: 1 addition & 1 deletion ext/dom/config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ if test "$PHP_DOM" != "no"; then
PHP_SETUP_LIBXML(DOM_SHARED_LIBADD, [
AC_DEFINE(HAVE_DOM,1,[ ])
PHP_NEW_EXTENSION(dom, [php_dom.c attr.c document.c \
domexception.c \
domexception.c parentnode.c \
processinginstruction.c cdatasection.c \
documentfragment.c domimplementation.c \
element.c node.c characterdata.c \
Expand Down
2 changes: 1 addition & 1 deletion ext/dom/config.w32
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ if (PHP_DOM == "yes") {
CHECK_HEADER_ADD_INCLUDE("libxml/parser.h", "CFLAGS_DOM", PHP_PHP_BUILD + "\\include\\libxml2")
) {
EXTENSION("dom", "php_dom.c attr.c document.c \
domexception.c processinginstruction.c \
domexception.c parentnode.c processinginstruction.c \
cdatasection.c documentfragment.c domimplementation.c element.c \
node.c characterdata.c documenttype.c \
entity.c nodelist.c text.c comment.c \
Expand Down
46 changes: 46 additions & 0 deletions ext/dom/document.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ const zend_function_entry php_dom_document_class_functions[] = { /* {{{ */
PHP_ME(domdocument, relaxNGValidateSource, arginfo_class_DOMDocument_relaxNGValidateSource, ZEND_ACC_PUBLIC)
#endif
PHP_ME(domdocument, registerNodeClass, arginfo_class_DOMDocument_registerNodeClass, ZEND_ACC_PUBLIC)
PHP_ME(domdocument, append, arginfo_class_DOMParentNode_append, ZEND_ACC_PUBLIC)
PHP_ME(domdocument, prepend, arginfo_class_DOMParentNode_prepend, ZEND_ACC_PUBLIC)
PHP_FE_END
};
/* }}} */
Expand Down Expand Up @@ -2128,4 +2130,48 @@ PHP_METHOD(domdocument, registerNodeClass)
}
/* }}} */

/* {{{ proto void domdocument::append(string|DOMNode ...$nodes)
URL: https://dom.spec.whatwg.org/#dom-parentnode-append
Since: DOM Living Standard (DOM4)
*/
PHP_METHOD(domdocument, append)
{
int argc;
zval *args, *id;
dom_object *intern;
xmlNode *context;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
RETURN_THROWS();
}

id = ZEND_THIS;
DOM_GET_OBJ(context, id, xmlNodePtr, intern);

dom_parent_node_append(intern, args, argc);
}
/* }}} */

/* {{{ proto void domdocument::prepend(string|DOMNode ...$nodes)
URL: https://dom.spec.whatwg.org/#dom-parentnode-prepend
Since: DOM Living Standard (DOM4)
*/
PHP_METHOD(domdocument, prepend)
{
int argc;
zval *args, *id;
dom_object *intern;
xmlNode *context;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
RETURN_THROWS();
}

id = ZEND_THIS;
DOM_GET_OBJ(context, id, xmlNodePtr, intern);

dom_parent_node_prepend(intern, args, argc);
}
/* }}} */

#endif /* HAVE_LIBXML && HAVE_DOM */
46 changes: 46 additions & 0 deletions ext/dom/documentfragment.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
const zend_function_entry php_dom_documentfragment_class_functions[] = {
PHP_ME(domdocumentfragment, __construct, arginfo_class_DOMDocumentFragment___construct, ZEND_ACC_PUBLIC)
PHP_ME(domdocumentfragment, appendXML, arginfo_class_DOMDocumentFragment_appendXML, ZEND_ACC_PUBLIC)
PHP_ME(domdocumentfragment, append, arginfo_class_DOMParentNode_append, ZEND_ACC_PUBLIC)
PHP_ME(domdocumentfragment, prepend, arginfo_class_DOMParentNode_prepend, ZEND_ACC_PUBLIC)
PHP_FE_END
};

Expand Down Expand Up @@ -137,4 +139,48 @@ PHP_METHOD(domdocumentfragment, appendXML) {
}
/* }}} */

/* {{{ proto void domdocumentfragment::append(string|DOMNode ...$nodes)
URL: https://dom.spec.whatwg.org/#dom-parentnode-append
Since: DOM Living Standard (DOM4)
*/
PHP_METHOD(domdocumentfragment, append)
{
int argc;
zval *args, *id;
dom_object *intern;
xmlNode *context;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
RETURN_THROWS();
}

id = ZEND_THIS;
DOM_GET_OBJ(context, id, xmlNodePtr, intern);

dom_parent_node_append(intern, args, argc);
}
/* }}} */

/* {{{ proto void domdocumentfragment::prepend(string|DOMNode ...$nodes)
URL: https://dom.spec.whatwg.org/#dom-parentnode-prepend
Since: DOM Living Standard (DOM4)
*/
PHP_METHOD(domdocumentfragment, prepend)
{
int argc;
zval *args, *id;
dom_object *intern;
xmlNode *context;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
RETURN_THROWS();
}

id = ZEND_THIS;
DOM_GET_OBJ(context, id, xmlNodePtr, intern);

dom_parent_node_prepend(intern, args, argc);
}
/* }}} */

#endif
31 changes: 27 additions & 4 deletions ext/dom/dom.stub.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
<?php

interface DOMChildNode
{
public function remove(): void;

/** @var ...DOMNode|string $nodes */
public function before(... $nodes): void;

/** @var ...DOMNode|string $nodes */
public function after(...$nodes): void;

/** @var ...DOMNode|string $nodes */
public function replaceWith(...$nodes): void;
}

interface DOMParentNode
{
/** @var ...DOMNode|string $nodes */
public function append(...$nodes): void;

/** @var ...DOMNode|string $nodes */
public function prepend(...$nodes): void;
}

class DOMNode {
/** @return DOMNode|false */
public function appendChild(DOMNode $newChild) {}
Expand Down Expand Up @@ -63,7 +86,7 @@ class DOMCdataSection {
public function __construct(string $value) {}
}

class DOMCharacterData {
class DOMCharacterData implements DOMChildNode {
/** @return bool */
public function appendData(string $data) {}

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

class DOMDocument {
class DOMDocument implements DOMParentNode {
public function __construct(string $version = "1.0", string $encoding = UNKNOWN) {}

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

class DOMDocumentFragment {
class DOMDocumentFragment implements DOMParentNode {
public function __construct() {}

/** @return bool */
public function appendXML(string $data) {}
}

class DOMElement {
class DOMElement implements DOMParentNode, DOMChildNode {
public function __construct(string $name, ?string $value = null, string $uri = "") {}

/** @return string */
Expand Down
15 changes: 15 additions & 0 deletions ext/dom/dom_arginfo.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
/* This is a generated file, edit the .stub.php file instead. */

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_DOMChildNode_remove, 0, 0, IS_VOID, 0)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_DOMChildNode_before, 0, 0, IS_VOID, 0)
ZEND_ARG_VARIADIC_INFO(0, nodes)
ZEND_END_ARG_INFO()

#define arginfo_class_DOMChildNode_after arginfo_class_DOMChildNode_before

#define arginfo_class_DOMChildNode_replaceWith arginfo_class_DOMChildNode_before

#define arginfo_class_DOMParentNode_append arginfo_class_DOMChildNode_before

#define arginfo_class_DOMParentNode_prepend arginfo_class_DOMChildNode_before

ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DOMNode_appendChild, 0, 0, 1)
ZEND_ARG_OBJ_INFO(0, newChild, DOMNode, 0)
ZEND_END_ARG_INFO()
Expand Down
16 changes: 16 additions & 0 deletions ext/dom/dom_fe.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#define DOM_FE_H

extern const zend_function_entry php_dom_domexception_class_functions[];
extern const zend_function_entry php_dom_parent_node_class_functions[];
extern const zend_function_entry php_dom_child_node_class_functions[];
extern const zend_function_entry php_dom_domimplementation_class_functions[];
extern const zend_function_entry php_dom_documentfragment_class_functions[];
extern const zend_function_entry php_dom_document_class_functions[];
Expand Down Expand Up @@ -75,6 +77,8 @@ PHP_METHOD(domimplementation, getFeature);
/* domdocumentfragment methods */
PHP_METHOD(domdocumentfragment, __construct);
PHP_METHOD(domdocumentfragment, appendXML);
PHP_METHOD(domdocumentfragment, append);
PHP_METHOD(domdocumentfragment, prepend);

/* domdocument methods */
PHP_METHOD(domdocument, createElement);
Expand Down Expand Up @@ -102,6 +106,8 @@ PHP_METHOD(domdocument, saveXML);
PHP_METHOD(domdocument, validate);
PHP_METHOD(domdocument, xinclude);
PHP_METHOD(domdocument, registerNodeClass);
PHP_METHOD(domdocument, append);
PHP_METHOD(domdocument, prepend);

#if defined(LIBXML_HTML_ENABLED)
PHP_METHOD(domdocument, loadHTML);
Expand Down Expand Up @@ -152,6 +158,10 @@ PHP_METHOD(domcharacterdata, appendData);
PHP_METHOD(domcharacterdata, insertData);
PHP_METHOD(domcharacterdata, deleteData);
PHP_METHOD(domcharacterdata, replaceData);
PHP_METHOD(domcharacterdata, remove);
PHP_METHOD(domcharacterdata, after);
PHP_METHOD(domcharacterdata, before);
PHP_METHOD(domcharacterdata, replaceWith);

/* domattr methods */
PHP_METHOD(domattr, isId);
Expand All @@ -177,6 +187,12 @@ PHP_METHOD(domelement, setIdAttribute);
PHP_METHOD(domelement, setIdAttributeNS);
PHP_METHOD(domelement, setIdAttributeNode);
PHP_METHOD(domelement, __construct);
PHP_METHOD(domelement, remove);
PHP_METHOD(domelement, after);
PHP_METHOD(domelement, before);
PHP_METHOD(domelement, append);
PHP_METHOD(domelement, prepend);
PHP_METHOD(domelement, replaceWith);

/* domtext methods */
PHP_METHOD(domtext, splitText);
Expand Down
Loading