<SOAP-ENV:Body>
<ProxyToolLaunchResponse>
<LaunchDirective>
<PerformRedirectAction>
http://127.0.0.1:80/~csev/nusoap/samples/LMSTool.php?session=6
</PerformRedirectAction>
</LaunchDirective>
</ProxyToolLaunchResponse>
<imsx_syncResponseHeaderInfo>
<imsx_version>1.0</imsx_version>
</imsx_syncResponseHeaderInfo>
</SOAP-ENV:Body>
The nusoap client parses it all and gets it all right and then only returns the first part. I added code
to lib/nusoap.php at line 5953 to detect if there were multiple root documents after parsing and
return an array of all of the root parts rather than just the first one.
Look for the string "theMessage".
<xs:complexType name="OutcomeProfile.Type" abstract="true">
<xs:annotation>
<xs:documentation>
</xs:documentation>
</xs:annotation>
<xs:sequence>
</xs:sequence>
</xs:complexType>
<xs:complexType name="MinimalOutcomeProfile.Type">
<xs:annotation>
<xs:documentation>
</xs:documentation>
<xs:annotation>
<xs:complexContent>
<xs:extension base="tns:OutcomeProfile.Type">
<xs:sequence>
<xs:element ref="tns:LaunchProfile" minOccurs = "1" maxOccurs = "1"/>
<xs:element ref="tns:Grade" minOccurs = "1" maxOccurs = "1"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="OutcomeMessageRequest">
<xs:complexType>
<xs:sequence>
<xs:element ref="tns:OutcomeProfile"/>
</xs:sequence>
</xs:complexType>
</xs:element>
The nusoap serializer wanted to serialize OutcomeMessageRequest so it went looking for
OutcomeProfile - if you put this in your array labelled "OutcomeProfile" it would see the
definition of the abstract class (OutcomeProfile.Type) and conclude there was nothing to serialize.
If you labeled things as "MinimalOutcomeProfile.Type" then nusoap would not see any relationship
between OutcomeMessage and MinimalOutcomeProfile.Type and again refuse to serialize.
The solution is a new feature I added to nusoap. The ideas is that you make an entry for "OutcomeProfile" and then within that, you point to the actual implementation of the type. Here is the syntax I used:
'SecurityProfile' => array (
"SOAP:Implementation" => "SharedSecretSecurityProfile.Type",
'SharedSecretSecurityProfile.Type' => array (
"MAC" => "00:ff:ff:ff:00:00"
)
)
You add a "SOAP:Implementation" tag within the entry for the abstract type and tell it the
real implementation type - it is basically like a redirect - "Hey you are typing to serialize
a SecurityProfile - but really the schema for this is actually a SharedSecretSecurityProfile.Type".
It works pretty well - I am not sure if I am generating good WSDL or not - I will have
to validate this with Axis (have I ever told you how much I despise it when WSDL hackers go
crazy and do elegant stuff?).
It serializes like this:
<SecurityProfile> <MAC">00:ff:ff:ff:00:00 </SecurityProfile>I don't think this is quite right because there is no real indication of the implementing type for the consuming folks. But I was happy just to get this to work at all. If someone who is a SOAP/WSDL expert can tell me how to fix this let me know. nusoap is a big hog/monster but I think I have a handle on it. The code is around line 5569 of lib/nusoap.php. Look for the string "Redirecting".
At the end of the day, it is no wonder that PHP folks really prefer REST.
/Chuck - Wed Feb 21 10:58:34 EST 2007