From 90ff4f8f52c466d42a208c4629be2d4981b553bb Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 20 Sep 2006 13:43:04 +0000 Subject: [PATCH] Added ability to make SOAP call userspace PHP<->XML converters --- ext/soap/php_encoding.c | 286 +++++++++++------------- ext/soap/php_encoding.h | 12 -- ext/soap/php_sdl.c | 4 - ext/soap/php_soap.h | 29 +-- ext/soap/soap.c | 383 +++++++++++++++++---------------- ext/soap/tests/typemap001.phpt | 60 ++++++ ext/soap/tests/typemap002.phpt | 56 +++++ ext/soap/tests/typemap003.phpt | 62 ++++++ ext/soap/tests/typemap004.phpt | 41 ++++ ext/soap/tests/typemap005.phpt | 61 ++++++ ext/soap/tests/typemap006.phpt | 57 +++++ ext/soap/tests/typemap007.phpt | 64 ++++++ ext/soap/tests/typemap008.phpt | 43 ++++ ext/soap/tests/typemap009.phpt | 56 +++++ ext/soap/tests/typemap010.phpt | 56 +++++ ext/soap/tests/typemap011.phpt | 52 +++++ ext/soap/tests/typemap012.phpt | 48 +++++ 17 files changed, 989 insertions(+), 381 deletions(-) create mode 100755 ext/soap/tests/typemap001.phpt create mode 100755 ext/soap/tests/typemap002.phpt create mode 100755 ext/soap/tests/typemap003.phpt create mode 100755 ext/soap/tests/typemap004.phpt create mode 100755 ext/soap/tests/typemap005.phpt create mode 100755 ext/soap/tests/typemap006.phpt create mode 100755 ext/soap/tests/typemap007.phpt create mode 100755 ext/soap/tests/typemap008.phpt create mode 100755 ext/soap/tests/typemap009.phpt create mode 100755 ext/soap/tests/typemap010.phpt create mode 100755 ext/soap/tests/typemap011.phpt create mode 100755 ext/soap/tests/typemap012.phpt diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index 4b5c90b985..4f8c53c08c 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -294,17 +294,30 @@ xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr par if (stype_str && zend_hash_find(ht, "enc_ns", sizeof("enc_ns"), (void **)&zns) == SUCCESS) { ns_str = soap_encode_string(*zns, NULL TSRMLS_CC); } - } - - if (SOAP_GLOBAL(sdl)) { - if (stype_str) { + if (SOAP_GLOBAL(sdl)) { if (ns_str) { enc = get_encoder(SOAP_GLOBAL(sdl), ns_str, stype_str); } else { enc = get_encoder_ex(SOAP_GLOBAL(sdl), stype_str, strlen(stype_str)); } } + if (enc == NULL && SOAP_GLOBAL(typemap)) { + encodePtr *new_enc; + smart_str nscat = {0}; + + if (ns_str != NULL) { + smart_str_appends(&nscat, ns_str); + smart_str_appendc(&nscat, ':'); + } + smart_str_appends(&nscat, stype_str); + smart_str_0(&nscat); + if (zend_hash_find(SOAP_GLOBAL(typemap), nscat.c, nscat.len + 1, (void**)&new_enc) == SUCCESS) { + enc = *new_enc; + } + smart_str_free(&nscat); + } } + if (enc == NULL) { enc = get_conversion(Z_LVAL_P(*ztype)); } @@ -394,15 +407,24 @@ xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr par if (encode == NULL) { encode = get_conversion(UNKNOWN_TYPE); } - if (encode->to_xml_before) { - data = encode->to_xml_before(&encode->details, data); + if (SOAP_GLOBAL(typemap) && encode->details.type_str) { + smart_str nscat = {0}; + encodePtr *new_enc; + + if (encode->details.ns) { + smart_str_appends(&nscat, encode->details.ns); + smart_str_appendc(&nscat, ':'); + } + smart_str_appends(&nscat, encode->details.type_str); + smart_str_0(&nscat); + if (zend_hash_find(SOAP_GLOBAL(typemap), nscat.c, nscat.len + 1, (void**)&new_enc) == SUCCESS) { + encode = *new_enc; + } + smart_str_free(&nscat); } if (encode->to_xml) { node = encode->to_xml(&encode->details, data, style, parent); } - if (encode->to_xml_after) { - node = encode->to_xml_after(&encode->details, node, style); - } } return node; } @@ -410,16 +432,52 @@ xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr par static zval *master_to_zval_int(encodePtr encode, xmlNodePtr data) { zval *ret = NULL; + TSRMLS_FETCH(); - if (encode->to_zval_before) { - data = encode->to_zval_before(&encode->details, data, 0); - } + if (SOAP_GLOBAL(typemap)) { + if (encode->details.type_str) { + smart_str nscat = {0}; + encodePtr *new_enc; + + if (encode->details.ns) { + smart_str_appends(&nscat, encode->details.ns); + smart_str_appendc(&nscat, ':'); + } + smart_str_appends(&nscat, encode->details.type_str); + smart_str_0(&nscat); + if (zend_hash_find(SOAP_GLOBAL(typemap), nscat.c, nscat.len + 1, (void**)&new_enc) == SUCCESS) { + encode = *new_enc; + } + smart_str_free(&nscat); + } else { + xmlAttrPtr type_attr = get_attribute_ex(data->properties,"type", XSI_NAMESPACE); + + if (type_attr != NULL) { + encodePtr *new_enc; + xmlNsPtr nsptr; + char *ns, *cptype; + smart_str nscat = {0}; + + parse_namespace(type_attr->children->content, &cptype, &ns); + nsptr = xmlSearchNs(data->doc, data, BAD_CAST(ns)); + if (nsptr != NULL) { + smart_str_appends(&nscat, (char*)nsptr->href); + smart_str_appendc(&nscat, ':'); + } + smart_str_appends(&nscat, cptype); + smart_str_0(&nscat); + efree(cptype); + if (ns) {efree(ns);} + if (zend_hash_find(SOAP_GLOBAL(typemap), nscat.c, nscat.len + 1, (void**)&new_enc) == SUCCESS) { + encode = *new_enc; + } + smart_str_free(&nscat); + } + } + } if (encode->to_zval) { ret = encode->to_zval(&encode->details, data); } - if (encode->to_zval_after) { - ret = encode->to_zval_after(&encode->details, ret); - } return ret; } @@ -458,125 +516,76 @@ zval *master_to_zval(encodePtr encode, xmlNodePtr data) return master_to_zval_int(encode, data); } -#ifdef HAVE_PHP_DOMXML -zval *to_xml_before_user(encodeTypePtr type, zval *data) -{ - TSRMLS_FETCH(); - - if (type.map->map_functions.to_xml_before) { - if (call_user_function(EG(function_table), NULL, type.map->map_functions.to_xml_before, data, 1, &data TSRMLS_CC) == FAILURE) { - soap_error0(E_ERROR, "Encoding: Error calling to_xml_before"); - } - } - return data; -} - xmlNodePtr to_xml_user(encodeTypePtr type, zval *data, int style, xmlNodePtr parent) { - zval *ret, **addr; - xmlNodePtr node; + xmlNodePtr ret = NULL; + zval *return_value; TSRMLS_FETCH(); - if (type.map->map_functions.to_xml) { - MAKE_STD_ZVAL(ret); - if (call_user_function(EG(function_table), NULL, type.map->map_functions.to_xml, ret, 1, &data TSRMLS_CC) == FAILURE) { - soap_error0(E_ERROR, "Encoding: Error calling to_xml"); - } + if (type && type->map && type->map->to_xml) { + MAKE_STD_ZVAL(return_value); - if (Z_TYPE_P(ret) != IS_OBJECT) { - soap_error0(E_ERROR, "Encoding: Error serializing object from to_xml_user"); + if (call_user_function(EG(function_table), NULL, type->map->to_xml, return_value, 1, &data TSRMLS_CC) == FAILURE) { + soap_error0(E_ERROR, "Encoding: Error calling to_xml callback"); } - - if (zend_hash_index_find(Z_OBJPROP_P(ret), 1, (void **)&addr) == SUCCESS) { - node = (xmlNodePtr)Z_LVAL_PP(addr); - node = xmlCopyNode(node, 1); - set_ns_and_type(node, type); + if (Z_TYPE_P(return_value) == IS_STRING) { + xmlDocPtr doc = soap_xmlParseMemory(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value)); + if (doc && doc->children) { + ret = xmlDocCopyNode(doc->children, parent->doc, 1); + } + xmlFreeDoc(doc); + } else if (Z_TYPE_P(return_value) == IS_UNICODE) { + char* str = soap_unicode_to_string(Z_USTRVAL_P(return_value), Z_USTRLEN_P(return_value) TSRMLS_CC); + int len = strlen(str); + xmlDocPtr doc = soap_xmlParseMemory(str, len); + if (doc && doc->children) { + ret = xmlDocCopyNode(doc->children, parent->doc, 1); + } + xmlFreeDoc(doc); + efree(str); } - zval_ptr_dtor(&ret); - } - return node; -} - -xmlNodePtr to_xml_after_user(encodeTypePtr type, xmlNodePtr node, int style) -{ - zval *ret, *param, **addr; - int found; - TSRMLS_FETCH(); - - if (type.map->map_functions.to_xml_after) { - MAKE_STD_ZVAL(ret); - MAKE_STD_ZVAL(param); - param = php_domobject_new(node, &found, NULL TSRMLS_CC); - if (call_user_function(EG(function_table), NULL, type.map->map_functions.to_xml_after, ret, 1, ¶m TSRMLS_CC) == FAILURE) { - soap_error0(E_ERROR, "Encoding: Error calling to_xml_after"); - } - if (zend_hash_index_find(Z_OBJPROP_P(ret), 1, (void **)&addr) == SUCCESS) { - node = (xmlNodePtr)Z_LVAL_PP(addr); - set_ns_and_type(node, type); - } - zval_ptr_dtor(&ret); - zval_ptr_dtor(¶m); + zval_ptr_dtor(&return_value); } - return node; -} - -xmlNodePtr to_zval_before_user(encodeTypePtr type, xmlNodePtr node, int style) -{ - zval *ret, *param, **addr; - int found; - TSRMLS_FETCH(); - - if (type.map->map_functions.to_zval_before) { - MAKE_STD_ZVAL(ret); - MAKE_STD_ZVAL(param); - param = php_domobject_new(node, &found, NULL TSRMLS_CC); - - if (call_user_function(EG(function_table), NULL, type.map->map_functions.to_zval_before, ret, 1, ¶m TSRMLS_CC) == FAILURE) { - soap_error0(E_ERROR, "Encoding: Error calling to_zval_before"); - } - if (zend_hash_index_find(Z_OBJPROP_P(ret), 1, (void **)&addr) == SUCCESS) { - node = (xmlNodePtr)Z_LVAL_PP(addr); - set_ns_and_type(node, type); - } - zval_ptr_dtor(&ret); - zval_ptr_dtor(¶m); + if (!ret) { + ret = xmlNewNode(NULL, BAD_CAST("BOGUS")); } - return node; + xmlAddChild(parent, ret); + if (style == SOAP_ENCODED) { + set_ns_and_type(ret, type); + } + return ret; } zval *to_zval_user(encodeTypePtr type, xmlNodePtr node) { - zval *ret, *param; - int found; + zval *return_value; TSRMLS_FETCH(); - if (type.map->map_functions.to_zval) { - MAKE_STD_ZVAL(ret); - MAKE_STD_ZVAL(param); - param = php_domobject_new(node, &found, NULL TSRMLS_CC); + if (type && type->map && type->map->to_zval) { + xmlBufferPtr buf; + zval *data; + xmlNodePtr copy; - if (call_user_function(EG(function_table), NULL, type.map->map_functions.to_zval, ret, 1, ¶m TSRMLS_CC) == FAILURE) { - soap_error0(E_ERROR, "Encoding: Error calling to_zval"); - } - zval_ptr_dtor(¶m); - efree(param); - } - return ret; -} + copy = xmlCopyNode(node, 1); + buf = xmlBufferCreate(); + xmlNodeDump(buf, NULL, copy, 0, 0); + MAKE_STD_ZVAL(data); + ZVAL_STRING(data, (char*)xmlBufferContent(buf), 1); + xmlBufferFree(buf); + xmlFreeNode(copy); -zval *to_zval_after_user(encodeTypePtr type, zval *data) -{ - TSRMLS_FETCH(); - - if (type.map->map_functions.to_zval_after) { - if (call_user_function(EG(function_table), NULL, type.map->map_functions.to_zval_after, data, 1, &data TSRMLS_CC) == FAILURE) { - soap_error0(E_ERROR, "Encoding: Error calling to_zval_after"); + ALLOC_INIT_ZVAL(return_value); + + if (call_user_function(EG(function_table), NULL, type->map->to_zval, return_value, 1, &data TSRMLS_CC) == FAILURE) { + soap_error0(E_ERROR, "Encoding: Error calling from_xml callback"); } + zval_ptr_dtor(&data); + } else { + ALLOC_INIT_ZVAL(return_value); } - return data; + return return_value; } -#endif /* TODO: get rid of "bogus".. ither by passing in the already created xmlnode or passing in the node name */ /* String encode/decode */ @@ -3070,26 +3079,8 @@ encodePtr get_conversion(int encode) TSRMLS_FETCH(); if (zend_hash_index_find(&SOAP_GLOBAL(defEncIndex), encode, (void **)&enc) == FAILURE) { - if (SOAP_GLOBAL(overrides)) { - smart_str nscat = {0}; - - smart_str_appendl(&nscat, (*enc)->details.ns, strlen((*enc)->details.ns)); - smart_str_appendc(&nscat, ':'); - smart_str_appendl(&nscat, (*enc)->details.type_str, strlen((*enc)->details.type_str)); - smart_str_0(&nscat); - - if (zend_hash_find(SOAP_GLOBAL(overrides), nscat.c, nscat.len + 1, (void **)&enc) == FAILURE) { - smart_str_free(&nscat); - soap_error0(E_ERROR, "Encoding: Cannot find encoding"); - return NULL; - } else { - smart_str_free(&nscat); - return *enc; - } - } else { - soap_error0(E_ERROR, "Encoding: Cannot find encoding"); - return NULL; - } + soap_error0(E_ERROR, "Encoding: Cannot find encoding"); + return NULL; } else { return *enc; } @@ -3286,32 +3277,11 @@ static void delete_mapping(void *data) { soapMappingPtr map = (soapMappingPtr)data; - if (map->ns) { - efree(map->ns); - } - if (map->ctype) { - efree(map->ctype); + if (map->to_xml) { + zval_ptr_dtor(&map->to_xml); } - - if (map->type == SOAP_MAP_FUNCTION) { - if (map->map_functions.to_xml_before) { - zval_ptr_dtor(&map->map_functions.to_xml_before); - } - if (map->map_functions.to_xml) { - zval_ptr_dtor(&map->map_functions.to_xml); - } - if (map->map_functions.to_xml_after) { - zval_ptr_dtor(&map->map_functions.to_xml_after); - } - if (map->map_functions.to_zval_before) { - zval_ptr_dtor(&map->map_functions.to_zval_before); - } - if (map->map_functions.to_zval) { - zval_ptr_dtor(&map->map_functions.to_zval); - } - if (map->map_functions.to_zval_after) { - zval_ptr_dtor(&map->map_functions.to_zval_after); - } + if (map->to_zval) { + zval_ptr_dtor(&map->to_zval); } efree(map); } diff --git a/ext/soap/php_encoding.h b/ext/soap/php_encoding.h index 2e92ec3757..c007925dd0 100644 --- a/ext/soap/php_encoding.h +++ b/ext/soap/php_encoding.h @@ -185,27 +185,15 @@ struct _encode { encodeType details; zval *(*to_zval)(encodeTypePtr type, xmlNodePtr data); xmlNodePtr (*to_xml)(encodeTypePtr type, zval *data, int style, xmlNodePtr parent); - - xmlNodePtr (*to_zval_before)(encodeTypePtr type, xmlNodePtr data, int style); - zval *(*to_zval_after)(encodeTypePtr type, zval *data); - - zval *(*to_xml_before)(encodeTypePtr type, zval *data); - xmlNodePtr (*to_xml_after)(encodeTypePtr type, xmlNodePtr data, int style); }; /* Master functions all encode/decode should be called thur these functions */ xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr parent); zval *master_to_zval(encodePtr encode, xmlNodePtr data); -#ifdef HAVE_PHP_DOMXML /* user defined mapping */ -zval *to_xml_before_user(encodeTypePtr type, zval *data); xmlNodePtr to_xml_user(encodeTypePtr type, zval *data, int style, xmlNodePtr parent); -xmlNodePtr to_xml_after_user(encodeTypePtr type, xmlNodePtr node, int style); -xmlNodePtr to_zval_before_user(encodeTypePtr type, xmlNodePtr node, int style); zval *to_zval_user(encodeTypePtr type, xmlNodePtr node); -zval *to_zval_after_user(encodeTypePtr type, zval *data); -#endif void whiteSpace_replace(xmlChar* str); void whiteSpace_collapse(xmlChar* str); diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c index f6f3dc1eba..106a282e8f 100644 --- a/ext/soap/php_sdl.c +++ b/ext/soap/php_sdl.c @@ -1326,10 +1326,6 @@ static void sdl_deserialize_encoder(encodePtr enc, sdlTypePtr *types, char **in) if (real_enc) { enc->to_zval = real_enc->to_zval; enc->to_xml = real_enc->to_xml; - enc->to_zval_before = real_enc->to_zval_before; - enc->to_xml_before = real_enc->to_xml_before; - enc->to_zval_after = real_enc->to_zval_after; - enc->to_xml_after = real_enc->to_xml_after; } } } diff --git a/ext/soap/php_soap.h b/ext/soap/php_soap.h index 02e753bd76..8230a96ae5 100644 --- a/ext/soap/php_soap.h +++ b/ext/soap/php_soap.h @@ -35,10 +35,6 @@ #include #include -#ifdef HAVE_PHP_DOMXML -# include "ext/domxml/php_domxml.h" -#endif - #ifndef PHP_HAVE_STREAMS # error You lose - must be compiled against PHP 4.3.0 or later #endif @@ -75,23 +71,8 @@ typedef struct _soapMapping soapMapping, *soapMappingPtr; #include "php_packet_soap.h" struct _soapMapping { - char *ns; - char *ctype; - int type; - - struct _map_functions { - zval *to_xml_before; - zval *to_xml; - zval *to_xml_after; - zval *to_zval_before; - zval *to_zval; - zval *to_zval_after; - } map_functions; - - struct _map_class { - int type; - zend_class_entry *ce; - } map_class; + zval *to_xml; + zval *to_zval; }; struct _soapHeader; @@ -101,9 +82,9 @@ typedef struct _soap_server_object { sdlPtr sdl; char *uri; - HashTable *mapping; int version; HashTable *class_map; + HashTable *typemap; int features; xmlCharEncodingHandlerPtr encoding; @@ -131,9 +112,9 @@ typedef struct _soap_client_object { sdlPtr sdl; char *uri; - HashTable *mapping; int version; HashTable *class_map; + HashTable *typemap; int features; xmlCharEncodingHandlerPtr encoding; @@ -222,7 +203,7 @@ ZEND_BEGIN_MODULE_GLOBALS(soap) HashTable defEncNs; /* mapping of default namespaces to prefixes */ HashTable defEnc; HashTable defEncIndex; - HashTable *overrides; + HashTable *typemap; int cur_uniq_ns; int soap_version; sdlPtr sdl; diff --git a/ext/soap/soap.c b/ext/soap/soap.c index f5bf40ca83..5d89c30fd7 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -172,9 +172,6 @@ PHP_METHOD(SoapServer, handle); PHP_METHOD(SoapServer, setPersistence); PHP_METHOD(SoapServer, fault); PHP_METHOD(SoapServer, addSoapHeader); -#ifdef HAVE_PHP_DOMXML -PHP_METHOD(PHP_SOAP_SERVER_CLASS, map); -#endif /* Client Functions */ PHP_METHOD(SoapClient, SoapClient); @@ -207,10 +204,6 @@ PHP_METHOD(SoapHeader, SoapHeader); #define SOAP_CTOR(class_name, func_name, arginfo, flags) ZEND_FENTRY(__construct, ZEND_MN(class_name##_##func_name), arginfo, flags) static zend_function_entry soap_functions[] = { -#ifdef HAVE_PHP_DOMXML - PHP_FE(soap_encode_to_xml, NULL) - PHP_FE(soap_encode_to_zval, NULL) -#endif PHP_FE(use_soap_error_handler, NULL) PHP_FE(is_soap_fault, NULL) {NULL, NULL, NULL} @@ -232,9 +225,6 @@ static zend_function_entry soap_server_functions[] = { PHP_ME(SoapServer, handle, NULL, 0) PHP_ME(SoapServer, fault, NULL, 0) PHP_ME(SoapServer, addSoapHeader, NULL, 0) -#ifdef HAVE_PHP_DOMXML - PHP_ME(SoapServer, map, NULL, 0) -#endif {NULL, NULL, NULL} }; @@ -503,7 +493,7 @@ static void php_soap_init_globals(zend_soap_globals *soap_globals TSRMLS_DC) soap_globals->defEnc = defEnc; soap_globals->defEncIndex = defEncIndex; soap_globals->defEncNs = defEncNs; - soap_globals->overrides = NULL; + soap_globals->typemap = NULL; soap_globals->use_soap_error_handler = 0; soap_globals->error_code = NULL; soap_globals->error_object = NULL; @@ -528,7 +518,7 @@ PHP_MSHUTDOWN_FUNCTION(soap) PHP_RINIT_FUNCTION(soap) { - SOAP_GLOBAL(overrides) = NULL; + SOAP_GLOBAL(typemap) = NULL; SOAP_GLOBAL(use_soap_error_handler) = 0; SOAP_GLOBAL(error_code) = NULL; SOAP_GLOBAL(error_object) = NULL; @@ -549,9 +539,9 @@ static void soap_server_dtor(void *object, zend_object_handle handle TSRMLS_DC) efree(service->soap_functions.ft); } - if (service->mapping) { - zend_hash_destroy(service->mapping); - efree(service->mapping); + if (service->typemap) { + zend_hash_destroy(service->typemap); + efree(service->typemap); } if (service->soap_class.argc) { @@ -596,7 +586,7 @@ static zend_object_value soap_server_ctor(zend_class_entry *ce TSRMLS_DC) obj->sdl = NULL; obj->uri = NULL; - obj->mapping = NULL; + obj->typemap = NULL; obj->version = SOAP_1_1; obj->class_map = NULL; obj->features = 0; @@ -624,9 +614,9 @@ static void soap_client_dtor(void *object, zend_object_handle handle TSRMLS_DC) { soap_client_object *client = (soap_client_object*)object; - if (client->mapping) { - zend_hash_destroy(client->mapping); - efree(client->mapping); + if (client->typemap) { + zend_hash_destroy(client->typemap); + efree(client->typemap); } if (client->uri) { efree(client->uri); @@ -721,7 +711,7 @@ static zend_object_value soap_client_ctor(zend_class_entry *ce TSRMLS_DC) obj->sdl = NULL; obj->uri = NULL; - obj->mapping = NULL; + obj->typemap = NULL; obj->version = SOAP_1_1; obj->class_map = NULL; obj->features = 0; @@ -894,43 +884,6 @@ PHP_MINFO_FUNCTION(soap) DISPLAY_INI_ENTRIES(); } -#ifdef HAVE_PHP_DOMXML -PHP_FUNCTION(soap_encode_to_xml) -{ - zval *pzval, *ret; - encodePtr enc; - char *name; - int found, name_len; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &name, &name_len, &pzval) == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters"); - } - - enc = get_conversion(Z_TYPE_P(pzval)); - ret = php_domobject_new(serialize_zval(pzval, NULL, name, SOAP_ENCODED), &found, NULL TSRMLS_CC); - *return_value = *ret; - zval_copy_ctor(return_value); - zval_ptr_dtor(&ret); -} - -PHP_FUNCTION(soap_encode_to_zval) -{ - zval *dom, **addr, *ret; - xmlNodePtr node; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &dom) == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters"); - } - - if (zend_hash_index_find(Z_OBJPROP_P(dom), 1, (void **)&addr) == FAILURE) { - } - - node = (xmlNodePtr)Z_LVAL_PP(addr); - ret = master_to_zval(NULL, node); - *return_value = *ret; -} -#endif - /* {{{ proto object SoapParam::SoapParam ( mixed data, string name) U SoapParam constructor */ PHP_METHOD(SoapParam, SoapParam) @@ -1202,6 +1155,133 @@ PHP_METHOD(SoapVar, SoapVar) /* }}} */ +static HashTable* soap_create_typemap(sdlPtr sdl, HashTable *ht TSRMLS_DC) +{ + zval **tmp; + HashTable *ht2; + HashPosition pos1, pos2; + HashTable *typemap = NULL; + + zend_hash_internal_pointer_reset_ex(ht, &pos1); + while (zend_hash_get_current_data_ex(ht, (void**)&tmp, &pos1) == SUCCESS) { + char *type_name = NULL; + char *type_ns = NULL; + char *free_type_name = NULL; + char *free_type_ns = NULL; + zval *to_xml = NULL; + zval *to_zval = NULL; + encodePtr enc, new_enc; + + if (Z_TYPE_PP(tmp) != IS_ARRAY) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Wrong 'typemap' option"); + } + ht2 = Z_ARRVAL_PP(tmp); + + zend_hash_internal_pointer_reset_ex(ht2, &pos2); + while (zend_hash_get_current_data_ex(ht2, (void**)&tmp, &pos2) == SUCCESS) { + zend_uchar name_type; + zstr name; + unsigned int name_len; + ulong index; + + name_type = zend_hash_get_current_key_ex(ht2, &name, &name_len, &index, 0, &pos2); + if (name_type == IS_STRING || name_type == IS_UNICODE) { + if (ZEND_U_EQUAL(name_type, name, name_len, "type_name", sizeof("type_name"))) { + if (Z_TYPE_PP(tmp) == IS_STRING) { + type_name = Z_STRVAL_PP(tmp); + } else if (Z_TYPE_PP(tmp) == IS_UNICODE) { + free_type_name = type_name = soap_unicode_to_string(Z_USTRVAL_PP(tmp), Z_USTRLEN_PP(tmp) TSRMLS_CC);; + } else if (Z_TYPE_PP(tmp) != IS_NULL) { + } + } else if (ZEND_U_EQUAL(name_type, name, name_len, "type_ns", sizeof("type_ns"))) { + if (Z_TYPE_PP(tmp) == IS_STRING) { + type_ns = Z_STRVAL_PP(tmp); + } else if (Z_TYPE_PP(tmp) == IS_UNICODE) { + free_type_ns = type_ns = soap_unicode_to_string(Z_USTRVAL_PP(tmp), Z_USTRLEN_PP(tmp) TSRMLS_CC);; + } else if (Z_TYPE_PP(tmp) != IS_NULL) { + } + } else if (ZEND_U_EQUAL(name_type, name, name_len, "to_xml", sizeof("to_xml"))) { + to_xml = *tmp; + } else if (ZEND_U_EQUAL(name_type, name, name_len, "from_xml", sizeof("from_xml"))) { + to_zval = *tmp; + } + } + zend_hash_move_forward_ex(ht2, &pos2); + } + + if (type_name) { + smart_str nscat = {0}; + + if (type_ns) { + enc = get_encoder(sdl, type_ns, type_name); + } else { + enc = get_encoder_ex(sdl, type_name, strlen(type_name)); + } + + new_enc = emalloc(sizeof(encode)); + memset(new_enc, 0, sizeof(encode)); + + if (enc) { + new_enc->details.type = enc->details.type; + new_enc->details.ns = estrdup(enc->details.ns); + new_enc->details.type_str = estrdup(enc->details.type_str); + new_enc->details.sdl_type = enc->details.sdl_type; + } else { + enc = get_conversion(UNKNOWN_TYPE); + new_enc->details.type = enc->details.type; + if (type_ns) { + new_enc->details.ns = estrdup(type_ns); + } + new_enc->details.type_str = estrdup(type_name); + } + new_enc->to_xml = enc->to_xml; + new_enc->to_zval = enc->to_zval; + new_enc->details.map = emalloc(sizeof(soapMapping)); + memset(new_enc->details.map, 0, sizeof(soapMapping)); + if (to_xml) { + zval_add_ref(&to_xml); + new_enc->details.map->to_xml = to_xml; + new_enc->to_xml = to_xml_user; + } else if (enc->details.map && enc->details.map->to_xml) { + zval_add_ref(&enc->details.map->to_xml); + new_enc->details.map->to_xml = enc->details.map->to_xml; + } + if (to_zval) { + zval_add_ref(&to_zval); + new_enc->details.map->to_zval = to_zval; + new_enc->to_zval = to_zval_user; + } else if (enc->details.map && enc->details.map->to_zval) { + zval_add_ref(&enc->details.map->to_zval); + new_enc->details.map->to_zval = enc->details.map->to_zval; + } + if (!typemap) { + typemap = emalloc(sizeof(HashTable)); + zend_hash_init(typemap, 0, NULL, delete_encoder, 0); + } + + if (type_ns) { + smart_str_appends(&nscat, type_ns); + smart_str_appendc(&nscat, ':'); + } + smart_str_appends(&nscat, type_name); + smart_str_0(&nscat); + zend_hash_update(typemap, nscat.c, nscat.len + 1, &new_enc, sizeof(encodePtr), NULL); + smart_str_free(&nscat); + } + + if (free_type_name) { + efree(free_type_name); + } + if (free_type_ns) { + efree(free_type_ns); + } + + zend_hash_move_forward_ex(ht, &pos1); + } + return typemap; +} + + /* {{{ proto object SoapServer::SoapServer ( mixed wsdl [, array options]) U SoapServer constructor */ PHP_METHOD(SoapServer, SoapServer) @@ -1211,6 +1291,7 @@ PHP_METHOD(SoapServer, SoapServer) char *wsdl = NULL; int version = SOAP_1_1; zend_bool cache_wsdl; + HashTable *typemap_ht = NULL; SOAP_SERVER_BEGIN_CODE(); @@ -1289,6 +1370,12 @@ PHP_METHOD(SoapServer, SoapServer) zend_hash_copy(service->class_map, (*tmp)->value.ht, (copy_ctor_func_t) zval_add_ref, (void *) &ztmp, sizeof(zval *)); } + if (zend_ascii_hash_find(ht, "typemap", sizeof("typemap"), (void**)&tmp) == SUCCESS && + Z_TYPE_PP(tmp) == IS_ARRAY && + zend_hash_num_elements(Z_ARRVAL_PP(tmp)) > 0) { + typemap_ht = Z_ARRVAL_PP(tmp); + } + if (zend_ascii_hash_find(ht, "features", sizeof("features"), (void**)&tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_LONG) { service->features = Z_LVAL_PP(tmp); @@ -1325,132 +1412,15 @@ PHP_METHOD(SoapServer, SoapServer) efree(wsdl); } + if (typemap_ht) { + service->typemap = soap_create_typemap(service->sdl, typemap_ht TSRMLS_CC); + } + SOAP_SERVER_END_CODE(); } /* }}} */ -#define NULL_OR_STRING(zval) \ - (!zval || Z_TYPE_P(zval) == IS_NULL || Z_TYPE_P(zval) == IS_STRING) - -#define IS_VALID_FUNCTION(zval) \ - (zval && Z_TYPE_P(zval) != IS_NULL) - -#ifdef HAVE_PHP_DOMXML -PHP_FUNCTION(PHP_SOAP_SERVER_CLASS, map) -{ - char *type, *class_name; - zval *to_xml_before = NULL, *to_xml = NULL, *to_xml_after = NULL, - *to_zval_before = NULL, *to_zval = NULL, *to_zval_after = NULL; - int type_len, class_name_len; - char *ns, *ctype; - soap_server_object *service; - - SOAP_SERVER_BEGIN_CODE(); - - if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "sz|zzzzz", - &type, &type_len, &to_xml_before, &to_xml, &to_xml_after, &to_zval_before, &to_zval, - &to_zval_after) == SUCCESS && NULL_OR_STRING(to_xml_before) && NULL_OR_STRING(to_xml) && - NULL_OR_STRING(to_xml_after) && NULL_OR_STRING(to_zval_before) && NULL_OR_STRING(to_zval) && - NULL_OR_STRING(to_zval_after)) { - - soapMappingPtr map; - encodePtr enc, new_enc; - smart_str resloved_ns = {0}; - - FETCH_THIS_SERVICE(service); - - new_enc = emalloc(sizeof(encode)); - memset(new_enc, 0, sizeof(encode)); - - ctype = strrchr(type, ':'); - if (ctype) { - smart_str_appendl(&resloved_ns, type, ctype - type); - smart_str_0(&resloved_ns); - ctype++; - } else { - ns = NULL; - } - - if (ns) { - if (zend_hash_find(SOAP_GLOBAL(defEncPrefix), resloved_ns.c, resloved_ns.len + 1, &ns) == SUCCESS) { - enc = get_encoder(service->sdl, ns, ctype); - smart_str_free(&resloved_ns); - smart_str_appendl(&resloved_ns, ns, strlen(ns)); - smart_str_appendc(&resloved_ns, ':'); - smart_str_appendl(&resloved_ns, ctype, strlen(ctype)); - smart_str_0(&resloved_ns); - type = resloved_ns.c; - type_len = resloved_ns.len; - } else { - enc = get_encoder_ex(service->sdl, type); - } - } else { - enc = get_encoder_ex(service->sdl, type); - } - - new_enc->details.type = enc->details.type; - new_enc->details.ns = estrdup(enc->details.ns); - new_enc->details.type_str = estrdup(enc->details.type_str); - new_enc->details.sdl_type = enc->details.sdl_type; - new_enc->to_xml = enc->to_xml; - new_enc->to_zval = enc->to_zval; - new_enc->to_xml_before = enc->to_xml_before; - new_enc->to_zval_before = enc->to_zval_before; - new_enc->to_xml_after = enc->to_xml_after; - new_enc->to_zval_after = enc->to_zval_after; - - map = emalloc(sizeof(soapMapping)); - memset(map, 0, sizeof(soapMapping)); - - map->type = SOAP_MAP_FUNCTION; - if (IS_VALID_FUNCTION(to_xml_before)) { - zval_add_ref(&to_xml_before); - map->map_functions.to_xml_before = to_xml_before; - new_enc->to_xml_before = to_xml_before_user; - } - if (IS_VALID_FUNCTION(to_xml)) { - zval_add_ref(&to_xml); - map->map_functions.to_xml = to_xml; - new_enc->to_xml = to_xml_user; - } - if (IS_VALID_FUNCTION(to_xml_after)) { - zval_add_ref(&to_xml_after); - map->map_functions.to_xml_after = to_xml_after; - new_enc->to_xml_after = to_xml_after_user; - } - if (IS_VALID_FUNCTION(to_zval_before)) { - zval_add_ref(&to_zval_before); - map->map_functions.to_zval_before = to_zval_before; - new_enc->to_zval_before = to_zval_before_user; - } - if (IS_VALID_FUNCTION(to_zval)) { - zval_add_ref(&to_zval); - map->map_functions.to_zval = to_zval; - new_enc->to_zval = to_zval_user; - } - if (IS_VALID_FUNCTION(to_zval_after)) { - zval_add_ref(&to_zval_after); - map->map_functions.to_zval_after = to_zval_after; - new_enc->to_zval_after = to_zval_after_user; - } - - new_enc->details.map = map; - - if (!service->mapping) { - service->mapping = emalloc(sizeof(HashTable)); - zend_hash_init(service->mapping, 0, NULL, delete_encoder, 0); - } - zend_hash_update(service->mapping, type, type_len + 1, &new_enc, sizeof(encodePtr), NULL); - smart_str_free(&resloved_ns); - } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &type, &type_len, &class_name, &class_name_len, &type) == SUCCESS) { - } else { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters"); - } -} -#endif - - /* {{{ proto object SoapServer::setPersistence ( int mode ) U Sets persistence mode of SoapServer */ PHP_METHOD(SoapServer, setPersistence) @@ -1711,7 +1681,7 @@ PHP_METHOD(SoapServer, handle) zstr arg = NULL_ZSTR; int arg_len; xmlCharEncodingHandlerPtr old_encoding; - HashTable *old_class_map; + HashTable *old_class_map, *old_typemap; int old_features; zend_uchar arg_type; @@ -1868,12 +1838,25 @@ PHP_METHOD(SoapServer, handle) SOAP_GLOBAL(encoding) = service->encoding; old_class_map = SOAP_GLOBAL(class_map); SOAP_GLOBAL(class_map) = service->class_map; + old_typemap = SOAP_GLOBAL(typemap); + SOAP_GLOBAL(typemap) = service->typemap; old_features = SOAP_GLOBAL(features); SOAP_GLOBAL(features) = service->features; old_soap_version = SOAP_GLOBAL(soap_version); function = deserialize_function_call(service->sdl, doc_request, service->actor, &function_name, &num_params, ¶ms, &soap_version, &soap_headers TSRMLS_CC); xmlFreeDoc(doc_request); +#ifdef ZEND_ENGINE_2 + if (EG(exception)) { + php_output_discard(TSRMLS_C); + if (Z_TYPE_P(EG(exception)) == IS_OBJECT && + instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) { + soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC); + } + goto fail; + } +#endif + service->soap_headers_ptr = &soap_headers; soap_obj = NULL; @@ -2110,14 +2093,32 @@ PHP_METHOD(SoapServer, handle) memcpy(response_name,Z_STRVAL(function_name),Z_STRLEN(function_name)); memcpy(response_name+Z_STRLEN(function_name),"Response",sizeof("Response")); } - SOAP_GLOBAL(overrides) = service->mapping; doc_return = serialize_response_call(function, response_name, service->uri, &retval, soap_headers, soap_version TSRMLS_CC); - SOAP_GLOBAL(overrides) = NULL; efree(response_name); } else { php_error_docref(NULL TSRMLS_CC, E_ERROR, "Function '%s' call failed", Z_STRVAL(function_name)); } +#ifdef ZEND_ENGINE_2 + if (EG(exception)) { + php_output_discard(TSRMLS_C); + if (Z_TYPE_P(EG(exception)) == IS_OBJECT && + instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) { + soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC); + } + if (service->type == SOAP_CLASS) { +#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION) + if (soap_obj && service->soap_class.persistance != SOAP_PERSISTENCE_SESSION) { +#else + if (soap_obj) { +#endif + zval_ptr_dtor(&soap_obj); + } + } + goto fail; + } +#endif + /* Flush buffer */ php_output_discard(TSRMLS_C); @@ -2158,6 +2159,7 @@ fail: SOAP_GLOBAL(encoding) = old_encoding; SOAP_GLOBAL(sdl) = old_sdl; SOAP_GLOBAL(class_map) = old_class_map; + SOAP_GLOBAL(typemap) = old_typemap; SOAP_GLOBAL(features) = old_features; /* Free soap headers */ @@ -2504,6 +2506,7 @@ PHP_METHOD(SoapClient, SoapClient) int soap_version = SOAP_1_1; php_stream_context *context = NULL; zend_bool cache_wsdl; + HashTable *typemap_ht = NULL; soap_client_object *client; SOAP_CLIENT_BEGIN_CODE(); @@ -2690,6 +2693,12 @@ PHP_METHOD(SoapClient, SoapClient) zend_hash_copy(client->class_map, (*tmp)->value.ht, (copy_ctor_func_t) zval_add_ref, (void *) &ztmp, sizeof(zval *)); } + if (zend_ascii_hash_find(ht, "typemap", sizeof("typemap"), (void**)&tmp) == SUCCESS && + Z_TYPE_PP(tmp) == IS_ARRAY && + zend_hash_num_elements(Z_ARRVAL_PP(tmp)) > 0) { + typemap_ht = Z_ARRVAL_PP(tmp); + } + if (zend_ascii_hash_find(ht, "features", sizeof("features"), (void**)&tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_LONG) { client->features = Z_LVAL_PP(tmp); @@ -2740,6 +2749,10 @@ PHP_METHOD(SoapClient, SoapClient) efree(wsdl); } + if (typemap_ht) { + client->typemap = soap_create_typemap(client->sdl, typemap_ht TSRMLS_CC); + } + SOAP_CLIENT_END_CODE(); } /* }}} */ @@ -2855,7 +2868,7 @@ static void do_soap_call(zval* this_ptr, int soap_version; zval response; xmlCharEncodingHandlerPtr old_encoding; - HashTable *old_class_map; + HashTable *old_class_map, *old_typemap; int old_features; soap_client_object *client; @@ -2894,6 +2907,8 @@ static void do_soap_call(zval* this_ptr, SOAP_GLOBAL(encoding) = client->encoding; old_class_map = SOAP_GLOBAL(class_map); SOAP_GLOBAL(class_map) = client->class_map; + old_typemap = SOAP_GLOBAL(typemap); + SOAP_GLOBAL(typemap) = client->typemap; old_features = SOAP_GLOBAL(features); SOAP_GLOBAL(features) = client->features; @@ -2990,7 +3005,8 @@ static void do_soap_call(zval* this_ptr, INIT_PZVAL(return_value); } } - if (Z_TYPE_P(return_value) == IS_OBJECT && + if (!EG(exception) && + Z_TYPE_P(return_value) == IS_OBJECT && instanceof_function(Z_OBJCE_P(return_value), soap_fault_class_entry TSRMLS_CC) && client->exceptions) { zval *exception; @@ -3002,6 +3018,7 @@ static void do_soap_call(zval* this_ptr, zend_throw_exception_object(exception TSRMLS_CC); } SOAP_GLOBAL(features) = old_features; + SOAP_GLOBAL(typemap) = old_typemap; SOAP_GLOBAL(class_map) = old_class_map; SOAP_GLOBAL(encoding) = old_encoding; SOAP_GLOBAL(sdl) = old_sdl; diff --git a/ext/soap/tests/typemap001.phpt b/ext/soap/tests/typemap001.phpt new file mode 100755 index 0000000000..d76170a748 --- /dev/null +++ b/ext/soap/tests/typemap001.phpt @@ -0,0 +1,60 @@ +--TEST-- +SOAP typemap 1: SoapServer support for typemap's from_xml() +--SKIPIF-- + +--FILE-- + + + + + foo + bar + + + + +"; + +function book_from_xml($xml) { + $sxe = simplexml_load_string($xml); + $obj = new book; + $obj->a = (string)$sxe->a; + $obj->b = (string)$sxe->b; + return $obj; +} + +class test{ + function dotest($book){ + $classname=get_class($book); + return "Object: ".$classname. "(".$book->a.",".$book->b.")"; + } +} + +class book{ + public $a="a"; + public $b="c"; + +} +$options=Array( + 'actor' =>'http://schemas.nothing.com', + 'typemap' => array(array("type_ns" => "http://schemas.nothing.com", + "type_name" => "book", + "from_xml" => "book_from_xml")) + ); + +$server = new SoapServer(dirname(__FILE__)."/classmap.wsdl",$options); +$server->setClass("test"); +$server->handle(); +echo "ok\n"; +?> +--EXPECT-- + +Object: book(foo,bar) +ok diff --git a/ext/soap/tests/typemap002.phpt b/ext/soap/tests/typemap002.phpt new file mode 100755 index 0000000000..ee80c5981c --- /dev/null +++ b/ext/soap/tests/typemap002.phpt @@ -0,0 +1,56 @@ +--TEST-- +SOAP typemap 2: SoapServer support for typemap's to_xml() +--SKIPIF-- + +--FILE-- + + + +??? + + + +"; + +function book_to_xml($book) { + return ''.$book->a.'!'.$book->b.'!'; +} + +class test{ + function dotest2($str){ + $book = new book; + $book->a = "foo"; + $book->b = "bar"; + return $book; + } +} + +class book{ + public $a="a"; + public $b="c"; + +} + +$options=Array( + 'actor' =>'http://schemas.nothing.com', + 'typemap' => array(array("type_ns" => "http://schemas.nothing.com", + "type_name" => "book", + "to_xml" => "book_to_xml")) + ); + +$server = new SoapServer(dirname(__FILE__)."/classmap.wsdl",$options); +$server->setClass("test"); +$server->handle(); +echo "ok\n"; +?> +--EXPECT-- + +foo!bar! +ok diff --git a/ext/soap/tests/typemap003.phpt b/ext/soap/tests/typemap003.phpt new file mode 100755 index 0000000000..d84181eb10 --- /dev/null +++ b/ext/soap/tests/typemap003.phpt @@ -0,0 +1,62 @@ +--TEST-- +SOAP Typemap 3: SoapClient support for typemap's from_xml() +--SKIPIF-- + +--FILE-- + + + + foo + bar + + +EOF; + } +} + +class book{ + public $a="a"; + public $b="c"; + +} + +function book_from_xml($xml) { + $sxe = simplexml_load_string($xml); + $obj = new book; + $obj->a = (string)$sxe->a; + $obj->b = (string)$sxe->b; + return $obj; +} + +$options=Array( + 'actor' =>'http://schemas.nothing.com', + 'typemap' => array(array("type_ns" => "http://schemas.nothing.com", + "type_name" => "book", + "from_xml" => "book_from_xml")) + ); + +$client = new TestSoapClient(dirname(__FILE__)."/classmap.wsdl",$options); +$ret = $client->dotest2("???"); +var_dump($ret); +echo "ok\n"; +?> +--EXPECTF-- +object(book)#%d (2) { + ["a"]=> + string(3) "foo" + ["b"]=> + string(3) "bar" +} +ok +--UEXPECTF-- +object(book)#%d (2) { + [u"a"]=> + unicode(3) "foo" + [u"b"]=> + unicode(3) "bar" +} +ok diff --git a/ext/soap/tests/typemap004.phpt b/ext/soap/tests/typemap004.phpt new file mode 100755 index 0000000000..f94af49900 --- /dev/null +++ b/ext/soap/tests/typemap004.phpt @@ -0,0 +1,41 @@ +--TEST-- +SOAP Typemap 4: SoapClient support for typemap's to_xml() +--SKIPIF-- + +--FILE-- +'.$book->a.'!'.$book->b.'!'; +} + +$options=Array( + 'actor' =>'http://schemas.nothing.com', + 'typemap' => array(array("type_ns" => "http://schemas.nothing.com", + "type_name" => "book", + "to_xml" => "book_to_xml")) + ); + +$client = new TestSoapClient(dirname(__FILE__)."/classmap.wsdl",$options); +$book = new book(); +$book->a = "foo"; +$book->b = "bar"; +$ret = $client->dotest($book); +var_dump($ret); +echo "ok\n"; +?> +--EXPECT-- + +foo!bar! diff --git a/ext/soap/tests/typemap005.phpt b/ext/soap/tests/typemap005.phpt new file mode 100755 index 0000000000..b016519a75 --- /dev/null +++ b/ext/soap/tests/typemap005.phpt @@ -0,0 +1,61 @@ +--TEST-- +SOAP typemap 5: SoapServer support for typemap's from_xml() (without WSDL) +--SKIPIF-- + +--FILE-- + + + + + foo + bar + + + + +"; + +function book_from_xml($xml) { + $sxe = simplexml_load_string($xml); + $obj = new book; + $obj->a = (string)$sxe->a; + $obj->b = (string)$sxe->b; + return $obj; +} + +class test{ + function dotest($book){ + $classname=get_class($book); + return "Object: ".$classname. "(".$book->a.",".$book->b.")"; + } +} + +class book{ + public $a="a"; + public $b="c"; + +} +$options=Array( + 'uri' => "http://schemas.nothing.com", + 'actor' => 'http://schemas.nothing.com', + 'typemap' => array(array("type_ns" => "http://schemas.nothing.com", + "type_name" => "book", + "from_xml" => "book_from_xml")) + ); + +$server = new SoapServer(NULL,$options); +$server->setClass("test"); +$server->handle(); +echo "ok\n"; +?> +--EXPECT-- + +Object: book(foo,bar) +ok diff --git a/ext/soap/tests/typemap006.phpt b/ext/soap/tests/typemap006.phpt new file mode 100755 index 0000000000..1e3609a8bc --- /dev/null +++ b/ext/soap/tests/typemap006.phpt @@ -0,0 +1,57 @@ +--TEST-- +SOAP typemap 6: SoapServer support for typemap's to_xml() (without WSDL, using SoapVar) +--SKIPIF-- + +--FILE-- + + + +??? + + + +"; + +function book_to_xml($book) { + return ''.$book->a.'!'.$book->b.'!'; +} + +class test{ + function dotest2($str){ + $book = new book; + $book->a = "foo"; + $book->b = "bar"; + return new SoapVar($book, null, "book", "http://schemas.nothing.com"); + } +} + +class book{ + public $a="a"; + public $b="c"; + +} + +$options=Array( + 'uri' => "http://schemas.nothing.com", + 'actor' => 'http://schemas.nothing.com', + 'typemap' => array(array("type_ns" => "http://schemas.nothing.com", + "type_name" => "book", + "to_xml" => "book_to_xml")) + ); + +$server = new SoapServer(NULL,$options); +$server->setClass("test"); +$server->handle(); +echo "ok\n"; +?> +--EXPECT-- + +foo!bar! +ok diff --git a/ext/soap/tests/typemap007.phpt b/ext/soap/tests/typemap007.phpt new file mode 100755 index 0000000000..b7ac1011ed --- /dev/null +++ b/ext/soap/tests/typemap007.phpt @@ -0,0 +1,64 @@ +--TEST-- +SOAP Typemap 7: SoapClient support for typemap's from_xml() (without WSDL) +--SKIPIF-- + +--FILE-- + + + + foo + bar + + +EOF; + } +} + +class book{ + public $a="a"; + public $b="c"; + +} + +function book_from_xml($xml) { + $sxe = simplexml_load_string($xml); + $obj = new book; + $obj->a = (string)$sxe->a; + $obj->b = (string)$sxe->b; + return $obj; +} + +$options=Array( + 'uri' => 'http://schemas.nothing.com', + 'location' => 'test://', + 'actor' => 'http://schemas.nothing.com', + 'typemap' => array(array("type_ns" => "http://schemas.nothing.com", + "type_name" => "book", + "from_xml" => "book_from_xml")) + ); + +$client = new TestSoapClient(NULL, $options); +$ret = $client->dotest2("???"); +var_dump($ret); +echo "ok\n"; +?> +--EXPECTF-- +object(book)#%d (2) { + ["a"]=> + string(3) "foo" + ["b"]=> + string(3) "bar" +} +ok +--UEXPECTF-- +object(book)#%d (2) { + [u"a"]=> + unicode(3) "foo" + [u"b"]=> + unicode(3) "bar" +} +ok diff --git a/ext/soap/tests/typemap008.phpt b/ext/soap/tests/typemap008.phpt new file mode 100755 index 0000000000..aaaa715d67 --- /dev/null +++ b/ext/soap/tests/typemap008.phpt @@ -0,0 +1,43 @@ +--TEST-- +SOAP Typemap 8: SoapClient support for typemap's to_xml() (without WSDL, using SoapVar) +--SKIPIF-- + +--FILE-- +'.$book->a.'!'.$book->b.'!'; +} + +$options=Array( + 'uri' => 'http://schemas.nothing.com', + 'location' => 'test://', + 'actor' => 'http://schemas.nothing.com', + 'typemap' => array(array("type_ns" => "http://schemas.nothing.com", + "type_name" => "book", + "to_xml" => "book_to_xml")) + ); + +$client = new TestSoapClient(NULL, $options); +$book = new book(); +$book->a = "foo"; +$book->b = "bar"; +$ret = $client->dotest(new SoapVar($book, null, "book", "http://schemas.nothing.com")); +var_dump($ret); +echo "ok\n"; +?> +--EXPECT-- + +foo!bar! diff --git a/ext/soap/tests/typemap009.phpt b/ext/soap/tests/typemap009.phpt new file mode 100755 index 0000000000..337aea65cc --- /dev/null +++ b/ext/soap/tests/typemap009.phpt @@ -0,0 +1,56 @@ +--TEST-- +SOAP typemap 9: SoapServer support for typemap's from_xml() (SoapFault) +--SKIPIF-- + +--FILE-- + + + + + foo + bar + + + + +"; + +function book_from_xml($xml) { + throw new SoapFault("Server", "Conversion Failed"); +} + +class test{ + function dotest($book){ + $classname=get_class($book); + return "Object: ".$classname. "(".$book->a.",".$book->b.")"; + } +} + +class book{ + public $a="a"; + public $b="c"; + +} +$options=Array( + 'actor' =>'http://schemas.nothing.com', + 'typemap' => array(array("type_ns" => "http://schemas.nothing.com", + "type_name" => "book", + "from_xml" => "book_from_xml")) + ); + +$server = new SoapServer(dirname(__FILE__)."/classmap.wsdl",$options); +$server->setClass("test"); +$server->handle(); +echo "ok\n"; +?> +--EXPECT-- + +SOAP-ENV:ServerConversion Failed +ok diff --git a/ext/soap/tests/typemap010.phpt b/ext/soap/tests/typemap010.phpt new file mode 100755 index 0000000000..44d2746bdd --- /dev/null +++ b/ext/soap/tests/typemap010.phpt @@ -0,0 +1,56 @@ +--TEST-- +SOAP typemap 10: SoapServer support for typemap's to_xml() (SoapFault) +--SKIPIF-- + +--FILE-- + + + +??? + + + +"; + +function book_to_xml($book) { + throw new SoapFault("Server", "Conversion Fault"); +} + +class test{ + function dotest2($str){ + $book = new book; + $book->a = "foo"; + $book->b = "bar"; + return $book; + } +} + +class book{ + public $a="a"; + public $b="c"; + +} + +$options=Array( + 'actor' =>'http://schemas.nothing.com', + 'typemap' => array(array("type_ns" => "http://schemas.nothing.com", + "type_name" => "book", + "to_xml" => "book_to_xml")) + ); + +$server = new SoapServer(dirname(__FILE__)."/classmap.wsdl",$options); +$server->setClass("test"); +$server->handle(); +echo "ok\n"; +?> +--EXPECT-- + +SOAP-ENV:ServerConversion Fault +ok diff --git a/ext/soap/tests/typemap011.phpt b/ext/soap/tests/typemap011.phpt new file mode 100755 index 0000000000..39b29b8ab2 --- /dev/null +++ b/ext/soap/tests/typemap011.phpt @@ -0,0 +1,52 @@ +--TEST-- +SOAP Typemap 11: SoapClient support for typemap's from_xml() (SoapFault) +--SKIPIF-- + +--FILE-- + + + + foo + bar + + +EOF; + } +} + +class book{ + public $a="a"; + public $b="c"; + +} + +function book_from_xml($xml) { + throw new SoapFault("Client", "Conversion Error"); +} + +$options=Array( + 'actor' =>'http://schemas.nothing.com', + 'typemap' => array(array("type_ns" => "http://schemas.nothing.com", + "type_name" => "book", + "from_xml" => "book_from_xml")) + ); + +$client = new TestSoapClient(dirname(__FILE__)."/classmap.wsdl",$options); +try { + $ret = $client->dotest2("???"); +} catch (SoapFault $e) { + $ret = "SoapFault = " . $e->faultcode . " - " . $e->faultstring; +} +var_dump($ret); +echo "ok\n"; +?> +--EXPECT-- +string(37) "SoapFault = Client - Conversion Error" +ok +--UEXPECT-- +unicode(37) "SoapFault = Client - Conversion Error" +ok diff --git a/ext/soap/tests/typemap012.phpt b/ext/soap/tests/typemap012.phpt new file mode 100755 index 0000000000..eee61ef5aa --- /dev/null +++ b/ext/soap/tests/typemap012.phpt @@ -0,0 +1,48 @@ +--TEST-- +SOAP Typemap 12: SoapClient support for typemap's to_xml() (SoapFault) +--SKIPIF-- + +--FILE-- +'http://schemas.nothing.com', + 'typemap' => array(array("type_ns" => "http://schemas.nothing.com", + "type_name" => "book", + "to_xml" => "book_to_xml")) + ); + +$client = new TestSoapClient(dirname(__FILE__)."/classmap.wsdl",$options); +$book = new book(); +$book->a = "foo"; +$book->b = "bar"; +try { + $ret = $client->dotest($book); +} catch (SoapFault $e) { + $ret = "SoapFault = " . $e->faultcode . " - " . $e->faultstring; +} +var_dump($ret); +echo "ok\n"; +?> +--EXPECT-- +string(37) "SoapFault = Client - Conversion Error" +ok +--UEXPECT-- +unicode(37) "SoapFault = Client - Conversion Error" +ok -- 2.50.1