From: Rob Richards Date: Mon, 22 May 2006 17:12:26 +0000 (+0000) Subject: MFH: add registerNodeClass() method X-Git-Tag: php-5.2.0RC1~488 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c384b34ae9269952ce9845b246db33cc4f4c0db1;p=php MFH: add registerNodeClass() method - update attribute isID functionality - add test --- diff --git a/ext/dom/attr.c b/ext/dom/attr.c index 9defda6273..355b6c572f 100644 --- a/ext/dom/attr.c +++ b/ext/dom/attr.c @@ -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; diff --git a/ext/dom/document.c b/ext/dom/document.c index 23233d8597..d814b764ac 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -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 */ diff --git a/ext/dom/dom_fe.h b/ext/dom/dom_fe.h index 78b0c94142..a12d2f9f77 100644 --- a/ext/dom/dom_fe.h +++ b/ext/dom/dom_fe.h @@ -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); diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index 73a604f136..80437a13e3 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -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); diff --git a/ext/dom/php_dom.h b/ext/dom/php_dom.h index d53440ba91..be1e956bfb 100644 --- a/ext/dom/php_dom.h +++ b/ext/dom/php_dom.h @@ -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 index 0000000000..5444cc4b9e --- /dev/null +++ b/ext/dom/tests/regsiter_node_class.phpt @@ -0,0 +1,43 @@ +--TEST-- +Test: registerNodeClass() +--SKIPIF-- + +--FILE-- +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 diff --git a/ext/dom/xml_common.h b/ext/dom/xml_common.h index 5cc709ad3a..a957ed61b8 100644 --- a/ext/dom/xml_common.h +++ b/ext/dom/xml_common.h @@ -24,17 +24,7 @@ #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;