## Developer Notes

Working with complex SOAP is a pain in PHP - I used nusoap because ti seemed to be a good place to start. My verison of nusoap is modified in two ways. I am not exactly sure if these modifications are right so folks should feel free to disagree with my mods or tell me that I am confused w.r.t SOAP.

## Support for Multi-Part Messages

It does not appear that nusoap client handles SOAP of the following form:

    <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".

## Support for Abstract Types

The IMS Tool Interoperability uses derived types and abstract classes. The nusoap outbound serialization seems to have NO support for this. Here is some sample WSDL:

    <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".

## What about PHP5?

This is all PHP4 because it comes shipped on my Mac :). So I use nusoap. In PHP5 some of this is built in and so either it is magically fixed or - it is broken and not easily fixed.

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