]> granicus.if.org Git - php/commitdiff
Fixed encoding of inhereted objects
authorDmitry Stogov <dmitry@php.net>
Wed, 1 Feb 2006 17:18:38 +0000 (17:18 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 1 Feb 2006 17:18:38 +0000 (17:18 +0000)
ext/soap/php_encoding.c
ext/soap/tests/classmap003.phpt [new file with mode: 0755]
ext/soap/tests/classmap003.wsdl [new file with mode: 0755]

index d03cdb2a938b45b0222f6489076c9d75670c357b..20e0dab5cf3ee4ebe56f7df2dd9515fa3dd5d1b7 100644 (file)
@@ -306,6 +306,34 @@ xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr par
                        xmlSetNs(node, nsp);
                }
        } else {
+               if (SOAP_GLOBAL(class_map) && data &&
+                   Z_TYPE_P(data) == IS_OBJECT &&
+                   !Z_OBJPROP_P(data)->nApplyCount) {
+                       zend_class_entry *ce = Z_OBJCE_P(data);
+                       HashPosition pos;
+                       zval **tmp;
+                       char *type_name = NULL;
+                       uint type_len;
+                       ulong idx;
+
+                       for (zend_hash_internal_pointer_reset_ex(SOAP_GLOBAL(class_map), &pos);
+                            zend_hash_get_current_data_ex(SOAP_GLOBAL(class_map), (void **) &tmp, &pos) == SUCCESS;
+                            zend_hash_move_forward_ex(SOAP_GLOBAL(class_map), &pos)) {
+                               if (Z_TYPE_PP(tmp) == IS_STRING &&
+                                   ce->name_length == Z_STRLEN_PP(tmp) &&
+                                   zend_binary_strncasecmp(ce->name, ce->name_length, Z_STRVAL_PP(tmp), ce->name_length, ce->name_length) == 0 &&
+                                   zend_hash_get_current_key_ex(SOAP_GLOBAL(class_map), &type_name, &type_len, &idx, 0, &pos) == HASH_KEY_IS_STRING) {
+
+                                   /* TODO: namespace isn't stored */
+                               encodePtr enc = get_encoder(SOAP_GLOBAL(sdl), SOAP_GLOBAL(sdl)->target_ns, type_name);
+                               if (enc) {
+                                       encode = &enc->details;
+                                       }                       
+                               break;
+                               }
+                       }
+               }
+
                if (encode == NULL) {
                        encode = get_conversion(UNKNOWN_TYPE);
                }
@@ -1221,9 +1249,9 @@ static zval *to_zval_object(encodeTypePtr type, xmlNodePtr data)
                                ret = master_to_zval_int(sdlType->encode, data);
                                FIND_XML_NULL(data, ret);
                                if (get_zval_property(ret, "any" TSRMLS_CC) != NULL) {
-                                 unset_zval_property(ret, "any" TSRMLS_CC);
+                                       unset_zval_property(ret, "any" TSRMLS_CC);
                                        redo_any = 1;
-                         }
+                               }
                                if (Z_TYPE_P(ret) == IS_OBJECT && ce != ZEND_STANDARD_CLASS_DEF_PTR) {
                                        zend_object *zobj = zend_objects_get_address(ret TSRMLS_CC);
                                        zobj->ce = ce;
@@ -1527,7 +1555,7 @@ static sdlTypePtr model_array_element(sdlContentModelPtr model)
 static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
 {
        xmlNodePtr xmlParam;
-       HashTable *prop;
+       HashTable *prop = NULL;
        int i;
        sdlTypePtr sdlType = type->sdl_type;
        TSRMLS_FETCH();
@@ -1535,19 +1563,19 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo
        if (!data || Z_TYPE_P(data) == IS_NULL) {
                xmlParam = xmlNewNode(NULL,"BOGUS");
                xmlAddChild(parent, xmlParam);
-         if (style == SOAP_ENCODED) {
+               if (style == SOAP_ENCODED) {
                        xmlSetProp(xmlParam, "xsi:nil", "true");
                }
                return xmlParam;
        }
 
+       if (Z_TYPE_P(data) == IS_OBJECT) {
+               prop = Z_OBJPROP_P(data);
+       } else if (Z_TYPE_P(data) == IS_ARRAY) {
+               prop = Z_ARRVAL_P(data);
+       }
+
        if (sdlType) {
-               prop = NULL;
-               if (Z_TYPE_P(data) == IS_OBJECT) {
-                       prop = Z_OBJPROP_P(data);
-               } else if (Z_TYPE_P(data) == IS_ARRAY) {
-                       prop = Z_ARRVAL_P(data);
-               }
                if (sdlType->kind == XSD_TYPEKIND_RESTRICTION &&
                    sdlType->encode && type != &sdlType->encode->details) {
                        encodePtr enc;
@@ -1563,7 +1591,7 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo
                                zval *tmp = get_zval_property(data, "_" TSRMLS_CC);
                                if (tmp) {
                                        xmlParam = master_to_xml(enc, tmp, style, parent);
-                               } else if (prop == NULL) {
+                               } else if (prop == NULL) {                                      
                                        xmlParam = master_to_xml(enc, data, style, parent);
                                } else {
                                        xmlParam = xmlNewNode(NULL,"BOGUS");
@@ -1579,7 +1607,10 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo
                            sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
                            sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
                            sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
+
+                               if (prop) prop->nApplyCount++;
                                xmlParam = master_to_xml(sdlType->encode, data, style, parent);
+                               if (prop) prop->nApplyCount--;
                        } else {
                                zval *tmp = get_zval_property(data, "_" TSRMLS_CC);
 
@@ -1596,7 +1627,6 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo
                        xmlParam = xmlNewNode(NULL,"BOGUS");
                        xmlAddChild(parent, xmlParam);
                }
-               FIND_ZVAL_NULL(data, xmlParam, style);
 
                if (prop != NULL) {
                  sdlTypePtr array_el;
@@ -1679,14 +1709,7 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo
        } else {
                xmlParam = xmlNewNode(NULL,"BOGUS");
                xmlAddChild(parent, xmlParam);
-               FIND_ZVAL_NULL(data, xmlParam, style);
 
-               prop = NULL;
-               if (Z_TYPE_P(data) == IS_OBJECT) {
-                       prop = Z_OBJPROP_P(data);
-               } else if (Z_TYPE_P(data) == IS_ARRAY) {
-                       prop = Z_ARRVAL_P(data);
-               }
                if (prop != NULL) {
                        i = zend_hash_num_elements(prop);
                        zend_hash_internal_pointer_reset(prop);
diff --git a/ext/soap/tests/classmap003.phpt b/ext/soap/tests/classmap003.phpt
new file mode 100755 (executable)
index 0000000..c126709
--- /dev/null
@@ -0,0 +1,54 @@
+--TEST--
+SOAP Classmap 3: encoding of inherited objects
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+ini_set("soap.wsdl_cache_enabled",0);
+
+class A {
+  public $x;
+  function __construct($a){
+    $this->x = $a;
+  }
+}
+
+class B extends A {
+  public $y; 
+  function __construct($a){
+    parent::__construct($a);
+    $this->y = $a + 1;
+  }
+}
+
+function f(){
+  return new B(5);
+}
+
+class LocalSoapClient extends SoapClient {
+
+  function __construct($wsdl, $options) {
+    parent::__construct($wsdl, $options);
+    $this->server = new SoapServer($wsdl, $options);
+    $this->server->addFunction("f");
+  }
+
+  function __doRequest($request, $location, $action, $version) {
+    ob_start();
+    $this->server->handle($request);
+    $response = ob_get_contents();
+    ob_end_clean();
+    return $response;
+  }
+}
+
+$client = new LocalSoapClient(dirname(__FILE__)."/classmap003.wsdl",
+    array('classmap'=>array('A'=>'A','B'=>'B')));
+print_r($client->f());
+?>
+--EXPECT--
+B Object
+(
+    [x] => 5
+    [y] => 6
+)
diff --git a/ext/soap/tests/classmap003.wsdl b/ext/soap/tests/classmap003.wsdl
new file mode 100755 (executable)
index 0000000..494c418
--- /dev/null
@@ -0,0 +1,51 @@
+<?xml version='1.0' encoding='UTF-8'?>\r
+\r
+<!-- WSDL file generated by Zend Studio. -->\r
+\r
+<definitions name="ab" targetNamespace="urn:ab" xmlns:typens="urn:ab" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/">\r
+       <types>\r
+               <xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:ab">\r
+                       <xsd:complexType name="A">\r
+                               <xsd:sequence>\r
+                                       <xsd:element name="x" type="xsd:anyType"/>\r
+                               </xsd:sequence>\r
+                       </xsd:complexType>\r
+                       <xsd:complexType name="B">\r
+                               <xsd:complexContent>\r
+                    <xsd:extension base="typens:A">\r
+                        <xsd:sequence>\r
+                                              <xsd:element name="y" type="xsd:anyType"/>\r
+                        </xsd:sequence>\r
+                    </xsd:extension>\r
+                </xsd:complexContent>\r
+                       </xsd:complexType>\r
+               </xsd:schema>\r
+       </types>\r
+       <message name="f"/>\r
+       <message name="fResponse">\r
+               <part name="fReturn" type="typens:A"/>\r
+       </message>\r
+       <portType name="abServerPortType">\r
+               <operation name="f">\r
+                       <input message="typens:f"/>\r
+                       <output message="typens:fResponse"/>\r
+               </operation>\r
+       </portType>\r
+       <binding name="abServerBinding" type="typens:abServerPortType">\r
+               <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>\r
+               <operation name="f">\r
+                       <soap:operation soapAction="urn:abServerAction"/>\r
+                       <input>\r
+                               <soap:body namespace="urn:ab" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>\r
+                       </input>\r
+                       <output>\r
+                               <soap:body namespace="urn:ab" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>\r
+                       </output>\r
+               </operation>\r
+       </binding>\r
+       <service name="abService">\r
+               <port name="abServerPort" binding="typens:abServerBinding">\r
+                       <soap:address location="http://localhost/abServer.php"/>\r
+               </port>\r
+       </service>\r
+</definitions>\r