Skip to content

Commit

Permalink
lots of wsdl work done, much more robust and conforming to wsdl spec
Browse files Browse the repository at this point in the history
literal encoding now supported
start towards support for document style soap messages, works to some
extent, still things to be done to properly handle some things


git-svn-id: http://svn.php.net/repository/pear/packages/SOAP/trunk@83655 c90b9560-bf6c-de11-be94-00142212c4b1
  • Loading branch information
Shane Caraveo committed May 27, 2002
1 parent 4de3823 commit 5a24a98
Show file tree
Hide file tree
Showing 6 changed files with 569 additions and 212 deletions.
151 changes: 66 additions & 85 deletions Base.php
Expand Up @@ -74,6 +74,11 @@
define('SOAP_SCHEMA_ENCODING', 'http://schemas.xmlsoap.org/soap/encoding/');
define('SOAP_ENVELOP', 'http://schemas.xmlsoap.org/soap/envelope/');

define('SCHEMA_SOAP', 'http://schemas.xmlsoap.org/wsdl/soap/');
define('SCHEMA_HTTP', 'http://schemas.xmlsoap.org/wsdl/http/');
define('SCHEMA_MIME', 'http://schemas.xmlsoap.org/wsdl/mime/');
define('SCHEMA_WSDL', 'http://schemas.xmlsoap.org/wsdl/');

define('SOAP_DEFAULT_ENCODING', 'UTF-8');

if (!function_exists('is_a'))
Expand Down Expand Up @@ -208,6 +213,14 @@ class SOAP_Base extends PEAR
var $fault = NULL;

var $wsdl = NULL;

/**
* section5
*
* @var boolean defines if we use section 5 encoding, or false if this is literal
*/
var $section5 = TRUE;

/**
* Constructor
*
Expand Down Expand Up @@ -318,7 +331,9 @@ function serializeValue($value, $name = '', $type = false, $elNamespace = NULL,
if (!$name || is_numeric($name)) $name = 'item';

if (!is_null($value)) {
list($ptype,$arrayType,$array_type_ns) = $this->_getSchemaType($type, $name, $typeNamespace);
$ptype = $arrayType = $array_type_ns = '';
if ($this->wsdl)
list($ptype,$arrayType,$array_type_ns) = $this->wsdl->getSchemaType($type, $name, $typeNamespace);
if (!$ptype) $ptype = $this->_getType($value);
if (!$type) $type = $ptype;

Expand Down Expand Up @@ -365,17 +380,19 @@ function serializeValue($value, $name = '', $type = false, $elNamespace = NULL,
}

$ar_size = count($value);
$numtypes = count($array_types);
$xmlout_offset = " SOAP-ENC:offset=\"[0]\"";
if ($numtypes == 1) $arrayType = $array_type;
// using anyType is more interoperable
if ($array_type == 'Struct') {
$array_type = '';
} else if ($array_type == 'Array') {
$arrayType = 'anyType';
$array_type_prefix = 'xsd';
} else
if (!$arrayType) $arrayType = $array_type;
if (!$arrayType) {
$numtypes = count($array_types);
if ($numtypes == 1) $arrayType = $array_type;
// using anyType is more interoperable
if ($array_type == 'Struct') {
$array_type = '';
} else if ($array_type == 'Array') {
$arrayType = 'anyType';
$array_type_prefix = 'xsd';
} else
if (!$arrayType) $arrayType = $array_type;
}
}
if (!isset($arrayType) || $numtypes > 1) {
$arrayType = 'xsd:anyType'; // should reference what schema we're using
Expand All @@ -398,8 +415,13 @@ function serializeValue($value, $name = '', $type = false, $elNamespace = NULL,
}
// add namespaces
if ($elNamespace) {
$elPrefix = $this->getNamespacePrefix($elNamespace);
$xmlout_name = "$elPrefix:$name";
if ($this->section5) {
$elPrefix = $this->getNamespacePrefix($elNamespace);
$xmlout_name = "$elPrefix:$name";
} else {
$xmlns = " xmlns=\"$elNamespace\"";
$xmlout_name = $name;
}
} else {
$xmlout_name = $name;
}
Expand All @@ -414,7 +436,7 @@ function serializeValue($value, $name = '', $type = false, $elNamespace = NULL,

// handle additional attributes
$xml_attr = '';
if (count($attributes)) {
if (count($attributes) > 0) {
foreach ($attributes as $k => $v) {
$kqn = new QName($k);
$vqn = new QName($v);
Expand All @@ -426,76 +448,26 @@ function serializeValue($value, $name = '', $type = false, $elNamespace = NULL,
if (isset($options['attachment']))
$this->attachments[] = $options['attachment'];

if ($xmlout_type) $xmlout_type = " xsi:type=\"$xmlout_type\"";
if (is_null($xmlout_value)) {
$xml = "\r\n<$xmlout_name$xmlout_type$xmlns$xml_attr/>";
} else {
$xml = "\r\n<$xmlout_name$xmlout_type$xmlns$xmlout_arrayType$xmlout_offset$xml_attr>".
$xmlout_value."</$xmlout_name>";
}
return $xml;
}

function _getSchemaType($type, $name, $type_namespace)
{
if ($this->wsdl) {
# see if it's a complex type so we can deal properly with SOAPENC:arrayType
if ($name && $type) {
# XXX TODO:
# look up the name in the wsdl and validate the type
foreach ($this->wsdl->complexTypes as $ns=> $types) {
if (array_key_exists($type, $types)) {
if (array_key_exists('base', $types[$type])) {
return array($types[$type]['base'],$types[$type]['type'],$this->wsdl->namespaces[$types[$type]['namespace']]);
}
if (array_key_exists('arrayType', $types[$type])) {
return array('Array',$types[$type]['arrayType'],$this->wsdl->namespaces[$types[$type]['namespace']]);
}
if (array_key_exists('elements', $types[$type]) &&
array_key_exists($name, $types[$type]['elements'])) {
$type = $types[$this->type]['elements']['type'];
return array($type,NULL,$this->wsdl->namespaces[$types[$type]['namespace']]);
}
}
}
if ($this->section5) {
if ($xmlout_type) $xmlout_type = " xsi:type=\"$xmlout_type\"";
if (is_null($xmlout_value)) {
$xml = "\r\n<$xmlout_name$xmlout_type$xmlns$xml_attr/>";
} else {
$xml = "\r\n<$xmlout_name$xmlout_type$xmlns$xmlout_arrayType$xmlout_offset$xml_attr>".
$xmlout_value."</$xmlout_name>";
}
if ($type && $type_namespace) {
$arrayType = NULL;
# XXX TODO:
# this code currently handles only one way of encoding array types in wsdl
# need to do a generalized function to figure out complex types
$p = $this->wsdl->ns[$type_namespace];
if ($p &&
array_key_exists($p, $this->wsdl->complexTypes) &&
array_key_exists($type, $this->wsdl->complexTypes[$p])) {
if ($arrayType = $this->wsdl->complexTypes[$p][$type]['arrayType']) {
$type = 'Array';
} else if ($this->wsdl->complexTypes[$p][$type]['order']=='sequence' &&
array_key_exists('elements', $this->wsdl->complexTypes[$p][$type])) {
reset($this->wsdl->complexTypes[$p][$type]['elements']);
# assume an array
if (count($this->wsdl->complexTypes[$p][$type]['elements']) == 1) {
$arg = current($this->wsdl->complexTypes[$p][$type]['elements']);
$arrayType = $arg['type'];
$type = 'Array';
} else {
foreach($this->wsdl->complexTypes[$p][$type]['elements'] as $element) {
if ($element['name'] == $type) {
$arrayType = $element['type'];
$type = $element['type'];
}
}
}
} else {
$type = 'Struct';
}
return array($type,$arrayType,$type_namespace);
}
} else {
if (is_null($xmlout_value)) {
$xml = "\r\n<$xmlout_name$xmlns$xml_attr/>";
} else {
$xml = "\r\n<$xmlout_name$xmlns$xml_attr>".
$xmlout_value."</$xmlout_name>";
}
}
return array(NULL,NULL,NULL);
return $xml;
}


/**
* SOAP::Value::_getType
*
Expand Down Expand Up @@ -672,24 +644,33 @@ function decode($soapval)
* @return associative array (headers,body)
* @access private
*/
function _makeEnvelope($method, $headers=NULL, $encoding = SOAP_DEFAULT_ENCODING)
function _makeEnvelope($method, $headers=NULL, $encoding = SOAP_DEFAULT_ENCODING,$options = array())
{
$header_xml = $ns_string = '';
$smsg = $header_xml = $ns_string = '';

if ($headers) {
foreach ($headers as $header) {
$header_xml .= $header->serialize($this);
}
$header_xml = "<SOAP-ENV:Header>\r\n$header_xml\r\n</SOAP-ENV:Header>\r\n";
}
$body = "<SOAP-ENV:Body>\r\n".$method->serialize($this)."\r\n</SOAP-ENV:Body>\r\n";
}
if (is_array($method)) {
foreach ($method as $part) {
$smsg .= $part->serialize($this);
}
} else {
$smsg = $method->serialize($this);
}
$body = "<SOAP-ENV:Body>\r\n".$smsg."\r\n</SOAP-ENV:Body>\r\n";

foreach ($this->_namespaces as $k => $v) {
$ns_string .= " xmlns:$v=\"$k\"\r\n ";
$ns_string .= " xmlns:$v=\"$k\"\r\n";
}

$xml = "<?xml version=\"1.0\" encoding=\"$encoding\"?>\r\n\r\n".
"<SOAP-ENV:Envelope $ns_string SOAP-ENV:encodingStyle=\"" . SOAP_SCHEMA_ENCODING . "\">\r\n".
"<SOAP-ENV:Envelope $ns_string".
($options['style'] == 'rpc'?" SOAP-ENV:encodingStyle=\"" . SOAP_SCHEMA_ENCODING . "\"":'').
">\r\n".
"$header_xml$body</SOAP-ENV:Envelope>\r\n";

return $xml;
Expand Down
21 changes: 16 additions & 5 deletions Client.php
Expand Up @@ -106,6 +106,7 @@ class SOAP_Client extends SOAP_Base
var $encoding = SOAP_DEFAULT_ENCODING;

var $headers = NULL;

/**
* SOAP_Client constructor
*
Expand Down Expand Up @@ -246,7 +247,7 @@ function call($method, $params = array(), $namespace = false, $soapAction = fals
if (count($opData['input']['parts']) > 0) {
$i = 0;
reset($params);
foreach ($opData['input']['parts'] as $name => $type) {
foreach ($opData['input']['parts'] as $name => $part) {
if (isset($params[$name])) {
$nparams[$name] = $params[$name];
} else {
Expand All @@ -259,9 +260,11 @@ function call($method, $params = array(), $namespace = false, $soapAction = fals
if (gettype($nparams[$name]) != 'object' ||
!is_a($nparams[$name],'soap_value')) {
// type is a qname likely, split it apart, and get the type namespace from wsdl
$qname = new QName($type);
$qname = new QName($part['type']);
if ($qname->ns)
$type_namespace = $this->wsdl->namespaces[$qname->ns];
else if (isset($part['namespace']))
$type_namespace = $this->wsdl->namespaces[$part['namespace']];
else
$type_namespace = NULL;
$qname->namespace = $type_namespace;
Expand All @@ -276,9 +279,17 @@ function call($method, $params = array(), $namespace = false, $soapAction = fals
}

// serialize the message
$mqname = new QName($method, $namespace);
$methodValue = new SOAP_Value($mqname->fqn(), 'Struct', $params);
$soap_msg = $this->_makeEnvelope($methodValue, $this->headers, $this->encoding);
$this->section5 = TRUE; // assume we encode with section 5
if (isset($options['use']) && $options['use']=='literal') $this->section5 = FALSE;

if (!isset($options['style']) || $options['style'] == 'rpc') {
$options['style'] = 'rpc';
$mqname = new QName($method, $namespace);
$methodValue = new SOAP_Value($mqname->fqn(), 'Struct', $params);
$soap_msg = $this->_makeEnvelope($methodValue, $this->headers, $this->encoding,$options);
} else {
$soap_msg = $this->_makeEnvelope($params, $this->headers, $this->encoding,$options);
}

if (PEAR::isError($soap_msg)) {
return $this->raiseSoapFault($soap_msg);
Expand Down
3 changes: 2 additions & 1 deletion Value.php
Expand Up @@ -79,7 +79,7 @@ class SOAP_Value
* @param mixed soap value {namespace}type, if not set an automatic
* @param mixed value to set
*/
function SOAP_Value($name = '', $type = false, $value)
function SOAP_Value($name = '', $type = false, $value, $attributes = array())
{
// detect type if not passed
$qn = new QName($name);
Expand All @@ -90,6 +90,7 @@ function SOAP_Value($name = '', $type = false, $value)
$this->type_prefix = $qn->ns;
$this->type_namespace = $qn->namespace;
$this->value = $value;
$this->attributes = $attributes;
}


Expand Down

0 comments on commit 5a24a98

Please sign in to comment.