]> granicus.if.org Git - php/commitdiff
MFH: add registerNodeClass() method
authorRob Richards <rrichards@php.net>
Mon, 22 May 2006 17:12:26 +0000 (17:12 +0000)
committerRob Richards <rrichards@php.net>
Mon, 22 May 2006 17:12:26 +0000 (17:12 +0000)
 - update attribute isID functionality
 - add test

ext/dom/attr.c
ext/dom/document.c
ext/dom/dom_fe.h
ext/dom/php_dom.c
ext/dom/php_dom.h
ext/dom/tests/regsiter_node_class.phpt [new file with mode: 0644]
ext/dom/xml_common.h

index 9defda6273f60727cb2608021641f8269a79db7b..355b6c572fd1328d27368a7a4bd436d805a4d284 100644 (file)
@@ -262,7 +262,6 @@ PHP_FUNCTION(dom_attr_is_id)
        zval *id;
        dom_object *intern;
        xmlAttrPtr attrp;
-       xmlNodePtr nodep;
 
        if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &id, dom_attr_class_entry) == FAILURE) {
                return;
@@ -270,9 +269,7 @@ PHP_FUNCTION(dom_attr_is_id)
 
        DOM_GET_OBJ(attrp, id, xmlAttrPtr, intern);
 
-       nodep = attrp->parent;
-
-       if (xmlIsID(attrp->doc, nodep, attrp)) {
+       if (attrp->atype == XML_ATTRIBUTE_ID) {
                RETURN_TRUE;
        } else {
                RETURN_FALSE;
index 23233d85977700639551921cc13bbb60bc6e3525..d814b764ac16bfcadc2c1af41ab466fc5ba2ddc1 100644 (file)
@@ -85,6 +85,7 @@ zend_function_entry php_dom_document_class_functions[] = {
        PHP_FALIAS(relaxNGValidate, dom_document_relaxNG_validate_file, NULL)
        PHP_FALIAS(relaxNGValidateSource, dom_document_relaxNG_validate_xml, NULL)
 #endif
+       PHP_ME(domdocument, registerNodeClass, NULL, ZEND_ACC_PUBLIC)
        {NULL, NULL, NULL}
 };
 
@@ -384,7 +385,7 @@ Since: DOM Level 3
 */
 int dom_document_strict_error_checking_read(dom_object *obj, zval **retval TSRMLS_DC)
 {
-       dom_doc_props *doc_prop;
+       dom_doc_propsptr doc_prop;
 
        ALLOC_ZVAL(*retval);
        if (obj->document) {
@@ -399,7 +400,7 @@ int dom_document_strict_error_checking_read(dom_object *obj, zval **retval TSRML
 int dom_document_strict_error_checking_write(dom_object *obj, zval *newval TSRMLS_DC)
 {
        zval value_copy;
-       dom_doc_props *doc_prop;
+       dom_doc_propsptr doc_prop;
 
        if(newval->refcount > 1) {
                value_copy = *newval;
@@ -427,7 +428,7 @@ readonly=no
 */
 int dom_document_format_output_read(dom_object *obj, zval **retval TSRMLS_DC)
 {
-       dom_doc_props *doc_prop;
+       dom_doc_propsptr doc_prop;
 
        ALLOC_ZVAL(*retval);
        if (obj->document) {
@@ -442,7 +443,7 @@ int dom_document_format_output_read(dom_object *obj, zval **retval TSRMLS_DC)
 int dom_document_format_output_write(dom_object *obj, zval *newval TSRMLS_DC)
 {
        zval value_copy;
-       dom_doc_props *doc_prop;
+       dom_doc_propsptr doc_prop;
 
        if(newval->refcount > 1) {
                value_copy = *newval;
@@ -469,7 +470,7 @@ readonly=no
 */
 int    dom_document_validate_on_parse_read(dom_object *obj, zval **retval TSRMLS_DC)
 {
-       dom_doc_props *doc_prop;
+       dom_doc_propsptr doc_prop;
 
        ALLOC_ZVAL(*retval);
        if (obj->document) {
@@ -484,7 +485,7 @@ int dom_document_validate_on_parse_read(dom_object *obj, zval **retval TSRMLS_DC
 int dom_document_validate_on_parse_write(dom_object *obj, zval *newval TSRMLS_DC)
 {
        zval value_copy;
-       dom_doc_props *doc_prop;
+       dom_doc_propsptr doc_prop;
 
        if(newval->refcount > 1) {
                value_copy = *newval;
@@ -512,7 +513,7 @@ readonly=no
 */
 int dom_document_resolve_externals_read(dom_object *obj, zval **retval TSRMLS_DC)
 {
-       dom_doc_props *doc_prop;
+       dom_doc_propsptr doc_prop;
 
        ALLOC_ZVAL(*retval);
        if (obj->document) {
@@ -527,7 +528,7 @@ int dom_document_resolve_externals_read(dom_object *obj, zval **retval TSRMLS_DC
 int dom_document_resolve_externals_write(dom_object *obj, zval *newval TSRMLS_DC)
 {
        zval value_copy;
-       dom_doc_props *doc_prop;
+       dom_doc_propsptr doc_prop;
 
        if(newval->refcount > 1) {
                value_copy = *newval;
@@ -555,7 +556,7 @@ readonly=no
 */
 int dom_document_preserve_whitespace_read(dom_object *obj, zval **retval TSRMLS_DC)
 {
-       dom_doc_props *doc_prop;
+       dom_doc_propsptr doc_prop;
 
        ALLOC_ZVAL(*retval);
        if (obj->document) {
@@ -570,7 +571,7 @@ int dom_document_preserve_whitespace_read(dom_object *obj, zval **retval TSRMLS_
 int dom_document_preserve_whitespace_write(dom_object *obj, zval *newval TSRMLS_DC)
 {
        zval value_copy;
-       dom_doc_props *doc_prop;
+       dom_doc_propsptr doc_prop;
 
        if(newval->refcount > 1) {
                value_copy = *newval;
@@ -597,7 +598,7 @@ readonly=no
 */
 int dom_document_recover_read(dom_object *obj, zval **retval TSRMLS_DC)
 {
-       dom_doc_props *doc_prop;
+       dom_doc_propsptr doc_prop;
 
        ALLOC_ZVAL(*retval);
        if (obj->document) {
@@ -612,7 +613,7 @@ int dom_document_recover_read(dom_object *obj, zval **retval TSRMLS_DC)
 int dom_document_recover_write(dom_object *obj, zval *newval TSRMLS_DC)
 {
        zval value_copy;
-       dom_doc_props *doc_prop;
+       dom_doc_propsptr doc_prop;
 
        if(newval->refcount > 1) {
                value_copy = *newval;
@@ -640,7 +641,7 @@ readonly=no
 */
 int dom_document_substitue_entities_read(dom_object *obj, zval **retval TSRMLS_DC)
 {
-       dom_doc_props *doc_prop;
+       dom_doc_propsptr doc_prop;
 
        ALLOC_ZVAL(*retval);
        if (obj->document) {
@@ -655,7 +656,7 @@ int dom_document_substitue_entities_read(dom_object *obj, zval **retval TSRMLS_D
 int dom_document_substitue_entities_write(dom_object *obj, zval *newval TSRMLS_DC)
 {
        zval value_copy;
-       dom_doc_props *doc_prop;
+       dom_doc_propsptr doc_prop;
 
        if(newval->refcount > 1) {
                value_copy = *newval;
@@ -1410,7 +1411,7 @@ char *_dom_get_valid_file_path(char *source, char *resolved_path, int resolved_p
 static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, int options TSRMLS_DC) {
     xmlDocPtr ret;
     xmlParserCtxtPtr ctxt = NULL;
-       dom_doc_props *doc_props;
+       dom_doc_propsptr doc_props;
        dom_object *intern;
        php_libxml_ref_obj *document = NULL;
        int validate, recover, resolve_externals, keep_blanks, substitute_ent;
@@ -1436,10 +1437,6 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, int optio
 
        xmlInitParser();
 
-#if LIBXML_VERSION < 20600
-       keep_blanks = xmlKeepBlanksDefault(keep_blanks);
-#endif
-
        if (mode == DOM_LOAD_FILE) {
                char *file_dest = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN  TSRMLS_CC);
                if (file_dest) {
@@ -1450,14 +1447,6 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, int optio
                ctxt = xmlCreateDocParserCtxt(source);
        }
 
-#if LIBXML_VERSION < 20600
-       xmlKeepBlanksDefault(keep_blanks);
-       /* xmlIndentTreeOutput default is changed in xmlKeepBlanksDefault
-       reset back to 1 which is default value */
-
-       xmlIndentTreeOutput = 1;
-#endif
-
        if (ctxt == NULL) {
                return(NULL);
        }
@@ -1490,7 +1479,6 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, int optio
                ctxt->sax->warning = php_libxml_ctx_warning;
        }
 
-#if LIBXML_VERSION >= 20600
        if (validate && ! (options & XML_PARSE_DTDVALID)) {
                options |= XML_PARSE_DTDVALID;
        }
@@ -1505,11 +1493,6 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, int optio
        }
 
        xmlCtxtUseOptions(ctxt, options);
-#else
-       ctxt->validate = validate;
-    ctxt->loadsubset = (resolve_externals * XML_COMPLETE_ATTRS);
-       ctxt->replaceEntities = substitute_ent;
-#endif
 
        ctxt->recovery = recover;
        if (recover) {
@@ -1544,7 +1527,7 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, int optio
 static void dom_parse_document(INTERNAL_FUNCTION_PARAMETERS, int mode) {
        zval *id, *rv = NULL;
        xmlDoc *docp = NULL, *newdoc;
-       dom_doc_props *doc_prop;
+       dom_doc_propsptr doc_prop;
        dom_object *intern;
        char *source;
        int source_len, refcount, ret;
@@ -1626,7 +1609,7 @@ PHP_FUNCTION(dom_document_save)
        xmlDoc *docp;
        int file_len = 0, bytes, format, saveempty;
        dom_object *intern;
-       dom_doc_props *doc_props;
+       dom_doc_propsptr doc_props;
        char *file;
        long options = 0;
 
@@ -1672,7 +1655,7 @@ PHP_FUNCTION(dom_document_savexml)
        xmlBufferPtr buf;
        xmlChar *mem;
        dom_object *intern, *nodeobj;
-       dom_doc_props *doc_props;
+       dom_doc_propsptr doc_props;
        int size, format, saveempty;
        long options = 0;
 
@@ -1781,11 +1764,7 @@ PHP_FUNCTION(dom_document_xinclude)
 
        DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
 
-#if LIBXML_VERSION >= 20607
        err = xmlXIncludeProcessFlags(docp, flags);
-#else
-       err = xmlXIncludeProcess (docp);
-#endif
 
        /* XML_XINCLUDE_START and XML_XINCLUDE_END nodes need to be removed as these
        are added via xmlXIncludeProcess to mark beginning and ending of xincluded document 
@@ -2034,7 +2013,7 @@ static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode)
        zval *id, *rv = NULL;
        xmlDoc *docp = NULL, *newdoc;
        dom_object *intern;
-       dom_doc_props *doc_prop;
+       dom_doc_propsptr doc_prop;
        char *source;
        int source_len, refcount, ret;
        htmlParserCtxtPtr ctxt;
@@ -2128,7 +2107,7 @@ PHP_FUNCTION(dom_document_save_html_file)
        xmlDoc *docp;
        int file_len, bytes, format;
        dom_object *intern;
-       dom_doc_props *doc_props;
+       dom_doc_propsptr doc_props;
        char *file;
 
        if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &id, dom_document_class_entry, &file, &file_len) == FAILURE) {
@@ -2185,4 +2164,58 @@ PHP_FUNCTION(dom_document_save_html)
 
 #endif  /* defined(LIBXML_HTML_ENABLED) */
 
+/* {{{ proto boolean DOMDocument::registerNodeClass(string baseclass, string extendedclass);
+   Register extended class used to create base node type */
+PHP_METHOD(domdocument, registerNodeClass)
+{
+       zval *id;
+       xmlDoc *docp;
+       char *baseclass = NULL, *extendedclass = NULL;
+       int baseclass_len = 0, extendedclass_len = 0;
+       zend_class_entry *basece = NULL, *ce = NULL;
+       dom_object *intern;
+       zend_uchar type1, type2;
+
+       if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oss!", &id, dom_document_class_entry, &baseclass, &baseclass_len, &extendedclass, &extendedclass_len) == FAILURE) {
+               return;
+       }
+
+       if (baseclass_len) {
+               zend_class_entry **pce;
+               if (zend_lookup_class(baseclass, baseclass_len, &pce TSRMLS_CC) == FAILURE) {
+                       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Class %s does not exist", baseclass);
+                       return;
+               }
+               basece = *pce;
+       }
+
+       if (basece == NULL || ! instanceof_function(basece, dom_node_class_entry TSRMLS_CC)) {
+               php_error_docref(NULL TSRMLS_CC, E_ERROR, "Class %s is not derived from DOMNode.", baseclass);
+               return;
+       }
+
+       if (extendedclass_len) {
+               zend_class_entry **pce;
+               if (zend_lookup_class(extendedclass, extendedclass_len, &pce TSRMLS_CC) == FAILURE) {
+                       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Class %s does not exist", extendedclass);
+               }
+               ce = *pce;
+       }
+
+       if (ce == NULL || instanceof_function(ce, basece TSRMLS_CC)) {
+
+               DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
+
+               if (dom_set_doc_classmap(intern->document, basece, ce TSRMLS_CC) == FAILURE) {
+                       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Class %s could not be registered.", extendedclass);
+               }
+               RETURN_TRUE;
+       } else {
+               php_error_docref(NULL TSRMLS_CC, E_ERROR, "Class %s is not derived from %s.", extendedclass, baseclass);
+       }
+
+       RETURN_FALSE;
+}
+/* }}} */
+
 #endif  /* HAVE_LIBXML && HAVE_DOM */
index 78b0c94142067152e86468078ced2a1ad44cc82c..a12d2f9f77c9464590970cb08ab077dc265d6db0 100644 (file)
@@ -130,6 +130,7 @@ PHP_METHOD(domdocument, loadXML);
 PHP_FUNCTION(dom_document_savexml);
 PHP_FUNCTION(dom_document_validate);
 PHP_FUNCTION(dom_document_xinclude);
+PHP_METHOD(domdocument, registerNodeClass);
 
 #if defined(LIBXML_HTML_ENABLED)
 PHP_METHOD(domdocument, loadHTML);
index 73a604f136e9ba995be8bdcc1dd08a093a49db0e..80437a13e34a626c3c2248fcb575ca84e195967a 100644 (file)
@@ -148,12 +148,12 @@ int dom_node_children_valid(xmlNodePtr node) {
 /* {{{ dom_get_doc_props() */
 dom_doc_propsptr dom_get_doc_props(php_libxml_ref_obj *document)
 {
-       dom_doc_props *doc_props;
+       dom_doc_propsptr doc_props;
 
        if (document && document->doc_props) {
                return document->doc_props;
        } else {
-               doc_props = emalloc(sizeof(dom_doc_props));
+               doc_props = emalloc(sizeof(libxml_doc_props));
                doc_props->formatoutput = 0;
                doc_props->validateonparse = 0;
                doc_props->resolveexternals = 0;
@@ -161,18 +161,58 @@ dom_doc_propsptr dom_get_doc_props(php_libxml_ref_obj *document)
                doc_props->substituteentities = 0;
                doc_props->stricterror = 1;
                doc_props->recover = 0;
+               doc_props->classmap = NULL;
                if (document) {
                        document->doc_props = doc_props;
                }
                return doc_props;
        }
 }
+
+int dom_set_doc_classmap(php_libxml_ref_obj *document, zend_class_entry *basece, zend_class_entry *ce TSRMLS_DC)
+{
+       dom_doc_propsptr doc_props;
+
+       if (document) {
+               doc_props = dom_get_doc_props(document);
+               if (doc_props->classmap == NULL) {
+                       if (ce == NULL) {
+                               return SUCCESS;
+                       }
+                       ALLOC_HASHTABLE(doc_props->classmap);
+                       zend_hash_init(doc_props->classmap, 0, NULL, NULL, 0);
+               }
+               if (ce) {
+                       return zend_hash_add(doc_props->classmap, basece->name, basece->name_length + 1, &ce, sizeof(ce), NULL);
+               } else {
+                       return zend_hash_del(doc_props->classmap, basece->name, basece->name_length + 1);
+               }
+       }
+       return SUCCESS;
+}
+
+zend_class_entry *dom_get_doc_classmap(php_libxml_ref_obj *document, zend_class_entry *basece TSRMLS_DC)
+{
+       dom_doc_propsptr doc_props;
+       zend_class_entry **ce = NULL;
+       
+       if (document) {
+               doc_props = dom_get_doc_props(document);
+               if (doc_props->classmap) {
+                       if (zend_hash_find(doc_props->classmap, basece->name, basece->name_length + 1,  (void**) &ce) == SUCCESS) {
+                               return *ce;
+                       }
+               }
+       }
+
+       return basece;
+}
 /* }}} */
 
 /* {{{ dom_get_strict_error() */
 int dom_get_strict_error(php_libxml_ref_obj *document) {
        int stricterror;
-       dom_doc_props *doc_props;
+       dom_doc_propsptr doc_props;
 
        doc_props = dom_get_doc_props(document);
        stricterror = doc_props->stricterror;
@@ -1212,6 +1252,9 @@ PHP_DOM_EXPORT zval *php_dom_create_object(xmlNodePtr obj, int *found, zval *wra
                        return wrapper;
        }
 
+       if (domobj && domobj->document) {
+               ce = dom_get_doc_classmap(domobj->document, ce TSRMLS_CC);
+       }
        object_init_ex(wrapper, ce);
 
        intern = (dom_object *)zend_objects_get_address(wrapper TSRMLS_CC);
index d53440ba912b8f0c3411c4c345bc9899c4f44442..be1e956bfb6fc95178b3ab4cc51657538b4c04c9 100644 (file)
@@ -110,6 +110,7 @@ xmlNodePtr create_notation(const xmlChar *name, const xmlChar *ExternalID, const
 xmlNode *php_dom_libxml_hash_iter(xmlHashTable *ht, int index);
 xmlNode *php_dom_libxml_notation_iter(xmlHashTable *ht, int index);
 zend_object_iterator *php_dom_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC);
+int dom_set_doc_classmap(php_libxml_ref_obj *document, zend_class_entry *basece, zend_class_entry *ce TSRMLS_DC);
 
 #define REGISTER_DOM_CLASS(ce, name, parent_ce, funcs, entry) \
 INIT_CLASS_ENTRY(ce, name, funcs); \
diff --git a/ext/dom/tests/regsiter_node_class.phpt b/ext/dom/tests/regsiter_node_class.phpt
new file mode 100644 (file)
index 0000000..5444cc4
--- /dev/null
@@ -0,0 +1,43 @@
+--TEST--
+Test: registerNodeClass()
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+class myAttribute extends DOMAttr {
+   function testit() { return "HELLO Attribute"; }
+}
+
+class myElement extends DOMElement {
+   function testit() { return "HELLO Element"; }
+}
+
+$doc = new DOMDocument();
+$doc->registerNodeClass('DOMAttr', 'myAttribute');
+$doc->registerNodeClass('DOMElement', 'myElement');
+$doc->appendChild(new DOMElement('root'));
+$root = $doc->documentElement;
+$root->setAttribute('a', 'a1');
+var_dump($root);
+print $root->testit()."\n";
+$attr = $root->getAttributeNode('a');
+var_dump($attr);
+print $attr->testit()."\n";
+unset($attr);
+$doc->registerNodeClass('DOMAttr', NULL);
+$attr = $root->getAttributeNode('a');
+var_dump($attr);
+print $attr->testit()."\n";
+?>
+--EXPECTF--
+
+object(myElement)#%d (0) {
+}
+HELLO Element
+object(myAttribute)#%d (0) {
+}
+HELLO Attribute
+object(DOMAttr)#%d (0) {
+}
+
+Fatal error: Call to undefined method DOMAttr::testit() in %s on line 25
index 5cc709ad3a17a292d096b98087c798209ea27073..a957ed61b8f7f463c30a7b0a4ba6a3edf7ad090d 100644 (file)
 
 #include "ext/libxml/php_libxml.h"
 
-typedef struct _dom_doc_props {
-       int formatoutput;
-       int validateonparse;
-       int resolveexternals;
-       int preservewhitespace;
-       int substituteentities;
-       int stricterror;
-       int recover;
-} dom_doc_props;
-
-typedef dom_doc_props *dom_doc_propsptr;
+typedef libxml_doc_props *dom_doc_propsptr;
 
 typedef struct _dom_object {
        zend_object  std;