123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411 |
- /*
- +----------------------------------------------------------------------+
- | PHP Version 7 |
- +----------------------------------------------------------------------+
- | Copyright (c) The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | https://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Authors: Benjamin Eberlei <beberlei@php.net> |
- +----------------------------------------------------------------------+
- */
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #include "php.h"
- #if defined(HAVE_LIBXML) && defined(HAVE_DOM)
- #include "php_dom.h"
- /* {{{ firstElementChild DomParentNode
- readonly=yes
- URL: https://www.w3.org/TR/dom/#dom-parentnode-firstelementchild
- */
- int dom_parent_node_first_element_child_read(dom_object *obj, zval *retval)
- {
- xmlNode *nodep, *first = NULL;
- nodep = dom_object_get_node(obj);
- if (nodep == NULL) {
- php_dom_throw_error(INVALID_STATE_ERR, 1);
- return FAILURE;
- }
- if (dom_node_children_valid(nodep) == SUCCESS) {
- first = nodep->children;
- while (first && first->type != XML_ELEMENT_NODE) {
- first = first->next;
- }
- }
- if (!first) {
- ZVAL_NULL(retval);
- return SUCCESS;
- }
- php_dom_create_object(first, retval, obj);
- return SUCCESS;
- }
- /* }}} */
- /* {{{ lastElementChild DomParentNode
- readonly=yes
- URL: https://www.w3.org/TR/dom/#dom-parentnode-lastelementchild
- */
- int dom_parent_node_last_element_child_read(dom_object *obj, zval *retval)
- {
- xmlNode *nodep, *last = NULL;
- nodep = dom_object_get_node(obj);
- if (nodep == NULL) {
- php_dom_throw_error(INVALID_STATE_ERR, 1);
- return FAILURE;
- }
- if (dom_node_children_valid(nodep) == SUCCESS) {
- last = nodep->last;
- while (last && last->type != XML_ELEMENT_NODE) {
- last = last->prev;
- }
- }
- if (!last) {
- ZVAL_NULL(retval);
- return SUCCESS;
- }
- php_dom_create_object(last, retval, obj);
- return SUCCESS;
- }
- /* }}} */
- /* {{{ childElementCount DomParentNode
- readonly=yes
- https://www.w3.org/TR/dom/#dom-parentnode-childelementcount
- */
- int dom_parent_node_child_element_count(dom_object *obj, zval *retval)
- {
- xmlNode *nodep, *first = NULL;
- zend_long count = 0;
- nodep = dom_object_get_node(obj);
- if (nodep == NULL) {
- php_dom_throw_error(INVALID_STATE_ERR, 1);
- return FAILURE;
- }
- if (dom_node_children_valid(nodep) == SUCCESS) {
- first = nodep->children;
- while (first != NULL) {
- if (first->type == XML_ELEMENT_NODE) {
- count++;
- }
- first = first->next;
- }
- }
- ZVAL_LONG(retval, count);
- return SUCCESS;
- }
- /* }}} */
- xmlNode* dom_zvals_to_fragment(php_libxml_ref_obj *document, xmlNode *contextNode, zval *nodes, int nodesc)
- {
- int i;
- xmlDoc *documentNode;
- xmlNode *fragment;
- xmlNode *newNode;
- zend_class_entry *ce;
- dom_object *newNodeObj;
- int stricterror;
- if (document == NULL) {
- php_dom_throw_error(HIERARCHY_REQUEST_ERR, 1);
- return NULL;
- }
- if (contextNode->type == XML_DOCUMENT_NODE || contextNode->type == XML_HTML_DOCUMENT_NODE) {
- documentNode = (xmlDoc *) contextNode;
- } else {
- documentNode = contextNode->doc;
- }
- fragment = xmlNewDocFragment(documentNode);
- if (!fragment) {
- return NULL;
- }
- stricterror = dom_get_strict_error(document);
- for (i = 0; i < nodesc; i++) {
- if (Z_TYPE(nodes[i]) == IS_OBJECT) {
- ce = Z_OBJCE(nodes[i]);
- if (instanceof_function(ce, dom_node_class_entry)) {
- newNodeObj = Z_DOMOBJ_P(&nodes[i]);
- newNode = dom_object_get_node(newNodeObj);
- if (newNode->doc != documentNode) {
- xmlFree(fragment);
- php_dom_throw_error(WRONG_DOCUMENT_ERR, stricterror);
- return NULL;
- }
- if (newNode->parent != NULL) {
- xmlUnlinkNode(newNode);
- }
- newNodeObj->document = document;
- xmlSetTreeDoc(newNode, documentNode);
- if (newNode->type == XML_ATTRIBUTE_NODE) {
- xmlFree(fragment);
- php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror);
- return NULL;
- }
- if (!xmlAddChild(fragment, newNode)) {
- xmlFree(fragment);
- php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror);
- return NULL;
- }
- continue;
- } else {
- xmlFree(fragment);
- zend_argument_type_error(i + 1, "must be of type DOMNode|string, %s given", zend_zval_type_name(&nodes[i]));
- return NULL;
- }
- } else if (Z_TYPE(nodes[i]) == IS_STRING) {
- newNode = xmlNewDocText(documentNode, (xmlChar *) Z_STRVAL(nodes[i]));
- xmlSetTreeDoc(newNode, documentNode);
- if (!xmlAddChild(fragment, newNode)) {
- xmlFree(fragment);
- return NULL;
- }
- } else {
- xmlFree(fragment);
- zend_argument_type_error(i + 1, "must be of type DOMNode|string, %s given", zend_zval_type_name(&nodes[i]));
- return NULL;
- }
- }
- return fragment;
- }
- static void dom_fragment_assign_parent_node(xmlNodePtr parentNode, xmlNodePtr fragment)
- {
- xmlNodePtr node = fragment->children;
- while (node != NULL) {
- node->parent = parentNode;
- if (node == fragment->last) {
- break;
- }
- node = node->next;
- }
- fragment->children = NULL;
- fragment->last = NULL;
- }
- void dom_parent_node_append(dom_object *context, zval *nodes, int nodesc)
- {
- xmlNode *parentNode = dom_object_get_node(context);
- xmlNodePtr newchild, prevsib;
- xmlNode *fragment = dom_zvals_to_fragment(context->document, parentNode, nodes, nodesc);
- if (fragment == NULL) {
- return;
- }
- newchild = fragment->children;
- prevsib = parentNode->last;
- if (newchild) {
- if (prevsib != NULL) {
- prevsib->next = newchild;
- } else {
- parentNode->children = newchild;
- }
- parentNode->last = fragment->last;
- newchild->prev = prevsib;
- dom_fragment_assign_parent_node(parentNode, fragment);
- dom_reconcile_ns(parentNode->doc, newchild);
- }
- xmlFree(fragment);
- }
- void dom_parent_node_prepend(dom_object *context, zval *nodes, int nodesc)
- {
- xmlNode *parentNode = dom_object_get_node(context);
- if (parentNode->children == NULL) {
- dom_parent_node_append(context, nodes, nodesc);
- return;
- }
- xmlNodePtr newchild, nextsib;
- xmlNode *fragment = dom_zvals_to_fragment(context->document, parentNode, nodes, nodesc);
- if (fragment == NULL) {
- return;
- }
- newchild = fragment->children;
- nextsib = parentNode->children;
- if (newchild) {
- parentNode->children = newchild;
- fragment->last->next = nextsib;
- nextsib->prev = fragment->last;
- dom_fragment_assign_parent_node(parentNode, fragment);
- dom_reconcile_ns(parentNode->doc, newchild);
- }
- xmlFree(fragment);
- }
- void dom_parent_node_after(dom_object *context, zval *nodes, int nodesc)
- {
- xmlNode *prevsib = dom_object_get_node(context);
- xmlNodePtr newchild, parentNode;
- xmlNode *fragment;
- int stricterror = dom_get_strict_error(context->document);
- if (!prevsib->parent) {
- php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror);
- return;
- }
- parentNode = prevsib->parent;
- fragment = dom_zvals_to_fragment(context->document, parentNode, nodes, nodesc);
- if (fragment == NULL) {
- return;
- }
- newchild = fragment->children;
- if (newchild) {
- fragment->last->next = prevsib->next;
- prevsib->next = newchild;
- newchild->prev = prevsib;
- dom_fragment_assign_parent_node(parentNode, fragment);
- dom_reconcile_ns(prevsib->doc, newchild);
- }
- xmlFree(fragment);
- }
- void dom_parent_node_before(dom_object *context, zval *nodes, int nodesc)
- {
- xmlNode *nextsib = dom_object_get_node(context);
- xmlNodePtr newchild, prevsib, parentNode;
- xmlNode *fragment;
- prevsib = nextsib->prev;
- parentNode = nextsib->parent;
- fragment = dom_zvals_to_fragment(context->document, parentNode, nodes, nodesc);
- if (fragment == NULL) {
- return;
- }
- newchild = fragment->children;
- if (newchild) {
- if (parentNode->children == nextsib) {
- parentNode->children = newchild;
- } else {
- prevsib->next = newchild;
- }
- fragment->last->next = nextsib;
- nextsib->prev = fragment->last;
- newchild->prev = prevsib;
- dom_fragment_assign_parent_node(parentNode, fragment);
- dom_reconcile_ns(nextsib->doc, newchild);
- }
- xmlFree(fragment);
- }
- void dom_child_node_remove(dom_object *context)
- {
- xmlNode *child = dom_object_get_node(context);
- xmlNodePtr children;
- int stricterror;
- stricterror = dom_get_strict_error(context->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;
- }
- if (!child->parent) {
- php_dom_throw_error(NOT_FOUND_ERR, stricterror);
- return;
- }
- if (dom_node_children_valid(child->parent) == FAILURE) {
- return;
- }
- children = child->parent->children;
- if (!children) {
- php_dom_throw_error(NOT_FOUND_ERR, stricterror);
- return;
- }
- while (children) {
- if (children == child) {
- xmlUnlinkNode(child);
- return;
- }
- children = children->next;
- }
- php_dom_throw_error(NOT_FOUND_ERR, stricterror);
- }
- #endif
|