function _serializeValue(&$value, $name = '', $type = false, $elNamespace = null, $typeNamespace = null, $options = array(), $attributes = array(), $artype = '') { $namespaces = array(); $arrayType = $array_depth = $xmlout_value = null; $typePrefix = $elPrefix = $xmlout_offset = $xmlout_arrayType = ''; $xmlout_type = $xmlns = $ptype = $array_type_ns = ''; if (!$name || is_numeric($name)) { $name = 'item'; } if ($this->_wsdl) { list($ptype, $arrayType, $array_type_ns, $array_depth) = $this->_wsdl->getSchemaType($type, $name, $typeNamespace); } if (!$arrayType) { $arrayType = $artype; } if (!$ptype) { $ptype = $this->_getType($value); } if (!$type) { $type = $ptype; } if (strcasecmp($ptype, 'Struct') == 0 || strcasecmp($type, 'Struct') == 0) { // Struct $vars = null; if (is_object($value)) { $vars = get_object_vars($value); } else { $vars =& $value; } if (is_array($vars)) { foreach (array_keys($vars) as $k) { // Hide private vars. if ($k[0] == '_') { continue; } if (is_object($vars[$k])) { if (is_a($vars[$k], 'SOAP_Value')) { $xmlout_value .= $vars[$k]->serialize($this); } else { // XXX get the members and serialize them instead // converting to an array is more overhead than we // should really do. $xmlout_value .= $this->_serializeValue(get_object_vars($vars[$k]), $k, false, $this->_section5 ? null : $elNamespace); } } else { $xmlout_value .= $this->_serializeValue($vars[$k], $k, false, $this->_section5 ? null : $elNamespace); } } } } elseif (strcasecmp($ptype, 'Array') == 0 || strcasecmp($type, 'Array') == 0) { // Array. $typeNamespace = SOAP_SCHEMA_ENCODING; $orig_type = $type; $type = 'Array'; $numtypes = 0; $value = (array) $value; // XXX this will be slow on larger arrays. Basically, it flattens // arrays to allow us to serialize multi-dimensional arrays. We // only do this if arrayType is set, which will typically only // happen if we are using WSDL if (isset($options['flatten']) || $arrayType && (strchr($arrayType, ',') || strstr($arrayType, ']['))) { $numtypes = $this->_multiArrayType($value, $arrayType, $ar_size, $xmlout_value); } $array_type = $array_type_prefix = ''; if ($numtypes != 1) { $arrayTypeQName = new QName($arrayType); $arrayType = $arrayTypeQName->name; $array_types = array(); $array_val = null; // Serialize each array element. $ar_size = count($value); foreach ($value as $array_val) { if ($this->_isSoapValue($array_val)) { $array_type = $array_val->type; $array_types[$array_type] = 1; $array_type_ns = $array_val->type_namespace; $xmlout_value .= $array_val->serialize($this); } else { $array_type = $this->_getType($array_val); $array_types[$array_type] = 1; $xmlout_value .= $this->_serializeValue($array_val, 'item', $array_type, $this->_section5 ? null : $elNamespace); } } $xmlout_offset = ' SOAP-ENC:offset="[0]"'; if (!$arrayType) { $numtypes = count($array_types); if ($numtypes == 1) { $arrayType = $array_type; } // Using anyType is more interoperable. if ($array_type == 'Struct') { $array_type = ''; } elseif ($array_type == 'Array') { $arrayType = 'anyType'; $array_type_prefix = 'xsd'; } else { if (!$arrayType) { $arrayType = $array_type; } } } } if (!$arrayType || $numtypes > 1) { // Should reference what schema we're using. $arrayType = 'xsd:anyType'; } else { if ($array_type_ns) { $array_type_prefix = $this->_getNamespacePrefix($array_type_ns); } elseif (isset($this->_typemap[$this->_XMLSchemaVersion][$arrayType])) { $array_type_prefix = $this->_namespaces[$this->_XMLSchemaVersion]; } if ($array_type_prefix) { $arrayType = $array_type_prefix . ':' . $arrayType; } } $xmlout_arrayType = ' SOAP-ENC:arrayType="' . $arrayType; if ($array_depth != null) { for ($i = 0; $i < $array_depth; $i++) { $xmlout_arrayType .= '[]'; } } $xmlout_arrayType .= "[{$ar_size}]\""; } elseif ($this->_isSoapValue($value)) { $xmlout_value = $value->serialize($this); } elseif ($type == 'string') { $xmlout_value = htmlspecialchars($value); } elseif ($type == 'rawstring') { $xmlout_value =& $value; } elseif ($type == 'boolean') { $xmlout_value = $value ? 'true' : 'false'; } else { $xmlout_value =& $value; } // Add namespaces. if ($elNamespace) { $elPrefix = $this->_getNamespacePrefix($elNamespace); if ($elPrefix) { $xmlout_name = "{$elPrefix}:{$name}"; } else { $xmlout_name = $name; } } else { $xmlout_name = $name; } if ($typeNamespace) { $typePrefix = $this->_getNamespacePrefix($typeNamespace); if ($typePrefix) { $xmlout_type = "{$typePrefix}:{$type}"; } else { $xmlout_type = $type; } } elseif ($type && isset($this->_typemap[$this->_XMLSchemaVersion][$type])) { $typePrefix = $this->_namespaces[$this->_XMLSchemaVersion]; if ($typePrefix) { $xmlout_type = "{$typePrefix}:{$type}"; } else { $xmlout_type = $type; } } // Handle additional attributes. $xml_attr = ''; if (count($attributes)) { foreach ($attributes as $k => $v) { $kqn = new QName($k); $vqn = new QName($v); $xml_attr .= ' ' . $kqn->fqn() . '="' . $vqn->fqn() . '"'; } } // Store the attachment for mime encoding. if (isset($options['attachment']) && !PEAR::isError($options['attachment'])) { $this->_attachments[] = $options['attachment']; } 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}{$xmlout_arrayType}" . "{$xml_attr} xsi:nil=\"true\"/>"; } else { $xml = "\r\n<{$xmlout_name}{$xmlout_type}{$xmlns}{$xmlout_arrayType}" . "{$xmlout_offset}{$xml_attr}>{$xmlout_value}</{$xmlout_name}>"; } } 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 $xml; }
function &__generate($method, &$params, $namespace = false, $soapAction = false) { $this->fault = null; $this->__options['input'] = 'parse'; $this->__options['result'] = 'parse'; $this->__options['parameters'] = false; if ($params && gettype($params) != 'array') { $params = array($params); } if (gettype($namespace) == 'array') { foreach ($namespace as $optname => $opt) { $this->__options[strtolower($optname)] = $opt; } if (isset($this->__options['namespace'])) { $namespace = $this->__options['namespace']; } else { $namespace = false; } } else { // we'll place soapaction into our array for usage in the transport $this->__options['soapaction'] = $soapAction; $this->__options['namespace'] = $namespace; } if ($this->__endpointType == 'wsdl') { $this->_setSchemaVersion($this->_wsdl->xsd); // get portName if (!$this->_portName) { $this->_portName = $this->_wsdl->getPortName($method); } if (PEAR::isError($this->_portName)) { return $this->_raiseSoapFault($this->_portName); } // get endpoint $this->_endpoint = $this->_wsdl->getEndpoint($this->_portName); if (PEAR::isError($this->_endpoint)) { return $this->_raiseSoapFault($this->_endpoint); } // get operation data $opData = $this->_wsdl->getOperationData($this->_portName, $method); if (PEAR::isError($opData)) { return $this->_raiseSoapFault($opData); } $namespace = $opData['namespace']; $this->__options['style'] = $opData['style']; $this->__options['use'] = $opData['input']['use']; $this->__options['soapaction'] = $opData['soapAction']; // set input params if ($this->__options['input'] == 'parse') { $this->__options['parameters'] = $opData['parameters']; $nparams = array(); if (isset($opData['input']['parts']) && count($opData['input']['parts']) > 0) { $i = 0; reset($params); foreach ($opData['input']['parts'] as $name => $part) { $xmlns = ''; $attrs = array(); // is the name actually a complex type? if (isset($part['element'])) { $xmlns = $this->_wsdl->namespaces[$part['namespace']]; $part = $this->_wsdl->elements[$part['namespace']][$part['type']]; $name = $part['name']; } if (array_key_exists($name, $params) || $this->_wsdl->getDataHandler($name, $part['namespace'])) { $nparams[$name] =& $params[$name]; } else { // we now force an associative array for // parameters if using wsdl. return $this->_raiseSoapFault("The named parameter {$name} is not in the call parameters."); } 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($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; $type = $qname->name; $pqname = $name; if ($xmlns) { $pqname = '{' . $xmlns . '}' . $name; } $nparams[$name] = new SOAP_Value($pqname, $qname->fqn(), $nparams[$name], $attrs); } else { // wsdl fixups to the soap value. } } } $params =& $nparams; unset($nparams); } } else { $this->_setSchemaVersion(SOAP_XML_SCHEMA_VERSION); } // serialize the message. $this->_section5 = isset($this->__options['use']) && $this->__options['use'] == 'literal'; if (!isset($this->__options['style']) || $this->__options['style'] == 'rpc') { $this->__options['style'] = 'rpc'; $this->docparams = true; $mqname = new QName($method, $namespace); $methodValue = new SOAP_Value($mqname->fqn(), 'Struct', $params); $soap_msg =& $this->_makeEnvelope($methodValue, $this->headersOut, $this->_encoding, $this->__options); } else { if (!$params) { $mqname = new QName($method, $namespace); $mynull = null; $params = new SOAP_Value($mqname->fqn(), 'Struct', $mynull); } elseif ($this->__options['input'] == 'parse') { if (is_array($params)) { $nparams = array(); $keys = array_keys($params); foreach ($keys as $k) { if (gettype($params[$k]) != 'object') { $nparams[] = new SOAP_Value($k, false, $params[$k]); } else { $nparams[] =& $params[$k]; } } $params =& $nparams; } if ($this->__options['parameters']) { $mqname = new QName($method, $namespace); $params = new SOAP_Value($mqname->fqn(), 'Struct', $params); } } $soap_msg =& $this->_makeEnvelope($params, $this->headersOut, $this->_encoding, $this->__options); } unset($this->headersOut); if (PEAR::isError($soap_msg)) { return $this->_raiseSoapFault($soap_msg); } // handle Mime or DIME encoding // XXX DIME Encoding should move to the transport, do it here for now // and for ease of getting it done if (count($this->__attachments)) { if (isset($this->__options['attachments']) && $this->__options['attachments'] == 'Mime' || isset($this->__options['Mime'])) { $soap_msg =& $this->_makeMimeMessage($soap_msg, $this->_encoding); } else { // default is dime $soap_msg =& $this->_makeDIMEMessage($soap_msg, $this->_encoding); $this->__options['headers']['Content-Type'] = 'application/dime'; } if (PEAR::isError($soap_msg)) { return $this->_raiseSoapFault($soap_msg); } } // instantiate client if (is_array($soap_msg)) { $soap_data =& $soap_msg['body']; if (count($soap_msg['headers'])) { if (isset($this->__options['headers'])) { $this->__options['headers'] = array_merge($this->__options['headers'], $soap_msg['headers']); } else { $this->__options['headers'] = $soap_msg['headers']; } } } else { $soap_data =& $soap_msg; } return $soap_data; }
/** * Loops through the message, building response structures. * * @param integer $pos Position. * * @return SOAP_Value */ function _buildResponse($pos) { $response = null; if (isset($this->message[$pos]['children'])) { $children = explode('|', $this->message[$pos]['children']); foreach ($children as $c => $child_pos) { if ($this->message[$child_pos]['type'] != null) { $response[] = $this->_buildResponse($child_pos); } } if (isset($this->message[$pos]['arraySize'])) { $ardepth = count($this->message[$pos]['arraySize']); if ($ardepth > 1) { $ar = array_pad(array(), $ardepth, 0); if (isset($this->message[$pos]['arrayOffset'])) { for ($i = 0; $i < $ardepth; $i++) { $ar[$i] += $this->message[$pos]['arrayOffset'][$i]; } } $elc = count($response); for ($i = 0; $i < $elc; $i++) { // Recurse to build a multi dimensional array. $this->_domulti($ardepth, $ar, $newresp, $response[$i]); // Increment our array pointers. $ad = $ardepth - 1; $ar[$ad]++; while ($ad > 0 && $ar[$ad] >= $this->message[$pos]['arraySize'][$ad]) { $ar[$ad] = 0; $ad--; $ar[$ad]++; } } $response = $newresp; } elseif (isset($this->message[$pos]['arrayOffset']) && $this->message[$pos]['arrayOffset'][0] > 0) { // Check for padding. $pad = $this->message[$pos]['arrayOffset'][0] + count($response) * -1; $response = array_pad($response, $pad, null); } } } // Build attributes. $attrs = array(); foreach ($this->message[$pos]['attrs'] as $atn => $atv) { if (!strstr($atn, 'xmlns') && !strpos($atn, ':')) { $attrs[$atn] = $atv; } } // Add current node's value. if ($response) { $nqn = new QName($this->message[$pos]['name'], $this->message[$pos]['namespace']); $tqn = new QName($this->message[$pos]['type'], $this->message[$pos]['type_namespace']); $response = new SOAP_Value($nqn->fqn(), $tqn->fqn(), $response, $attrs); if (isset($this->message[$pos]['arrayType'])) { $response->arrayType = $this->message[$pos]['arrayType']; } } else { $nqn = new QName($this->message[$pos]['name'], $this->message[$pos]['namespace']); $tqn = new QName($this->message[$pos]['type'], $this->message[$pos]['type_namespace']); // Check if value is an empty array if ($tqn->name == 'Array') { $response =& new SOAP_Value($nqn->fqn(), $tqn->fqn(), array(), $attrs); } else { $response = new SOAP_Value($nqn->fqn(), $tqn->fqn(), $this->message[$pos]['cdata'], $attrs); } } // Handle header attribute that we need. if (array_key_exists('actor', $this->message[$pos])) { $response->actor = $this->message[$pos]['actor']; } if (array_key_exists('mustUnderstand', $this->message[$pos])) { $response->mustunderstand = $this->message[$pos]['mustUnderstand']; } return $response; }
function _serializeValue(&$value, $name = '', $type = false, $elNamespace = NULL, $typeNamespace=NULL, $options=array(), $attributes = array(), $artype='') { $namespaces = array(); $arrayType = $array_depth = $xmlout_value = null; $typePrefix = $elPrefix = $xmlout_offset = $xmlout_arrayType = $xmlout_type = $xmlns = ''; $ptype = $array_type_ns = ''; if (!$name || is_numeric($name)) { $name = 'item'; } if ($this->_wsdl) list($ptype, $arrayType, $array_type_ns, $array_depth) = $this->_wsdl->getSchemaType($type, $name, $typeNamespace); if (!$arrayType) $arrayType = $artype; if (!$ptype) $ptype = $this->_getType($value); if (!$type) $type = $ptype; if (strcasecmp($ptype,'Struct') == 0 || strcasecmp($type,'Struct') == 0) { // struct $vars = NULL; if (is_object($value)) { $vars = get_object_vars($value); } else { $vars = &$value; } if (is_array($vars)) { foreach (array_keys($vars) as $k) { if ($k[0]=='_') continue; // hide private vars if (is_object($vars[$k])) { if (is_a($vars[$k],'soap_value')) { $xmlout_value .= $vars[$k]->serialize($this); } else { // XXX get the members and serialize them instead // converting to an array is more overhead than we // should realy do, but php-soap is on it's way. $xmlout_value .= $this->_serializeValue(get_object_vars($vars[$k]), $k, false, $this->_section5?NULL:$elNamespace); } } else { $xmlout_value .= $this->_serializeValue($vars[$k],$k, false, $this->_section5?NULL:$elNamespace); } } } } else if (strcasecmp($ptype,'Array')==0 || strcasecmp($type,'Array')==0) { // array $typeNamespace = SOAP_SCHEMA_ENCODING; $orig_type = $type; $type = 'Array'; $numtypes = 0; // XXX this will be slow on larger array's. Basicly, it flattens array's to allow us // to serialize multi-dimensional array's. We only do this if arrayType is set, // which will typicaly only happen if we are using WSDL if (isset($options['flatten']) || ($arrayType && (strchr($arrayType,',') || strstr($arrayType,'][')))) { $numtypes = $this->_multiArrayType($value, $arrayType, $ar_size, $xmlout_value); } $array_type = $array_type_prefix = ''; if ($numtypes != 1) { $arrayTypeQName =new QName($arrayType); $arrayType = $arrayTypeQName->name; $array_types = array(); $array_val = NULL; // serialize each array element $ar_size = count($value); foreach ($value as $array_val) { if ($this->_isSoapValue($array_val)) { $array_type = $array_val->type; $array_types[$array_type] = 1; $array_type_ns = $array_val->type_namespace; $xmlout_value .= $array_val->serialize($this); } else { $array_type = $this->_getType($array_val); $array_types[$array_type] = 1; $xmlout_value .= $this->_serializeValue($array_val,'item', $array_type, $this->_section5?NULL:$elNamespace); } } $xmlout_offset = " SOAP-ENC:offset=\"[0]\""; 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 (!$arrayType || $numtypes > 1) { $arrayType = 'xsd:anyType'; // should reference what schema we're using } else { if ($array_type_ns) { $array_type_prefix = $this->_getNamespacePrefix($array_type_ns); } else if (array_key_exists($arrayType, $this->_typemap[$this->_XMLSchemaVersion])) { $array_type_prefix = $this->_namespaces[$this->_XMLSchemaVersion]; } if ($array_type_prefix) $arrayType = $array_type_prefix.':'.$arrayType; } $xmlout_arrayType = " SOAP-ENC:arrayType=\"" . $arrayType; if ($array_depth != null) { for ($i = 0; $i < $array_depth; $i++) { $xmlout_arrayType .= '[]'; } } $xmlout_arrayType .= "[$ar_size]\""; } else if ($this->_isSoapValue($value)) { $xmlout_value =& $value->serialize($this); } else if ($type == 'string') { $xmlout_value = htmlspecialchars($value); } else if ($type == 'rawstring') { $xmlout_value =& $value; } else if ($type == 'boolean') { $xmlout_value = $value?'true':'false'; } else { $xmlout_value =& $value; } // add namespaces if ($elNamespace) { $elPrefix = $this->_getNamespacePrefix($elNamespace); $xmlout_name = "$elPrefix:$name"; } else { $xmlout_name = $name; } if ($typeNamespace) { $typePrefix = $this->_getNamespacePrefix($typeNamespace); $xmlout_type = "$typePrefix:$type"; } else if ($type && array_key_exists($type, $this->_typemap[$this->_XMLSchemaVersion])) { $typePrefix = $this->_namespaces[$this->_XMLSchemaVersion]; $xmlout_type = "$typePrefix:$type"; } // handle additional attributes $xml_attr = ''; if (count($attributes) > 0) { foreach ($attributes as $k => $v) { $kqn =new QName($k); $vqn =new QName($v); $xml_attr .= ' '.$kqn->fqn().'="'.$vqn->fqn().'"'; } } // store the attachement for mime encoding if (isset($options['attachment'])) $this->__attachments[] = $options['attachment']; 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$xmlout_arrayType$xml_attr/>"; } else { $xml = "\r\n<$xmlout_name$xmlout_type$xmlns$xmlout_arrayType$xmlout_offset$xml_attr>". $xmlout_value."</$xmlout_name>"; } } 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 $xml; }
function parseRequest($data = '', $attachments = null) { /* Parse response, get SOAP_Parser object. */ $parser = new SOAP_Parser($data, $this->xml_encoding, $attachments); if ($parser->fault) { /* Fault occurred during message parsing. */ $this->fault = $parser->fault; return null; } if (!count($parser->root_struct_name)) { /* No method specified. */ $this->_raiseSoapFault('No method specified in request.'); return null; } /* Handle message headers. */ $request_headers = $parser->getHeaders(); $header_results = array(); if ($request_headers) { if (!is_a($request_headers, 'SOAP_Value')) { $this->_raiseSoapFault('Parser did not return SOAP_Value object: ' . $request_headers, '', '', 'Server'); return null; } if ($request_headers->value) { /* Handle headers now. */ foreach ($request_headers->value as $header_val) { $f_exists = $this->validateMethod($header_val->name, $header_val->namespace); /* TODO: this does not take into account message routing * yet. */ $myactor = !$header_val->actor || $header_val->actor == 'http://schemas.xmlsoap.org/soap/actor/next' || $header_val->actor == $this->endpoint; if (!$f_exists && $header_val->mustunderstand && $myactor) { $this->_raiseSoapFault('I don\'t understand header ' . $header_val->name, '', '', 'MustUnderstand'); return null; } /* We only handle the header if it's for us. */ $isok = $f_exists && $myactor; if ($isok) { /* Call our header now! */ $header_method = $header_val->name; $header_data = array($this->_decode($header_val)); /* If there are parameters to pass. */ $hr =& $this->callMethod($header_method, $header_data); if (PEAR::isError($hr)) { $this->_raiseSoapFault($hr); return null; } $results = $this->buildResult($hr, $this->return_type, $header_method, $header_val->namespace); $header_results[] = $results[0]; } } } } /* Handle the method call. */ /* Evaluate message, getting back a SOAP_Value object. */ $this->call_methodname = $this->methodname = $parser->root_struct_name[0]; /* Figure out the method namespace. */ $this->method_namespace = $parser->message[$parser->root_struct[0]]['namespace']; if ($this->_wsdl) { $this->_setSchemaVersion($this->_wsdl->xsd); $dataHandler = $this->_wsdl->getDataHandler($this->methodname, $this->method_namespace); if ($dataHandler) { $this->call_methodname = $this->methodname = $dataHandler; } $this->_portName = $this->_wsdl->getPortName($this->methodname); if (PEAR::isError($this->_portName)) { $this->_raiseSoapFault($this->_portName); return null; } $opData = $this->_wsdl->getOperationData($this->_portName, $this->methodname); if (PEAR::isError($opData)) { $this->_raiseSoapFault($opData); return null; } $this->_options['style'] = $opData['style']; $this->_options['use'] = $opData['output']['use']; $this->_options['parameters'] = $opData['parameters']; } /* Does method exist? */ if (!$this->methodname || !$this->validateMethod($this->methodname, $this->method_namespace)) { $this->_raiseSoapFault('method "' . $this->method_namespace . $this->methodname . '" not defined in service', '', '', 'Server'); return null; } if (!($request_val = $parser->getResponse())) { return null; } if (!is_a($request_val, 'SOAP_Value')) { $this->_raiseSoapFault('Parser did not return SOAP_Value object: ' . $request_val, '', '', 'Server'); return null; } /* Verify that SOAP_Value objects in request match the methods * signature. */ if (!$this->verifyMethod($request_val)) { /* verifyMethod() creates the fault. */ return null; } /* Need to set special error detection inside the value class to * differentiate between no params passed, and an error decoding. */ $request_data = $this->__decodeRequest($request_val); if (PEAR::isError($request_data)) { $this->_raiseSoapFault($request_data); return null; } $method_response =& $this->callMethod($this->call_methodname, $request_data); if (PEAR::isError($method_response)) { $this->_raiseSoapFault($method_response); return null; } if ($this->_options['parameters'] || !$method_response || $this->_options['style'] == 'rpc') { /* Get the method result. */ if (is_null($method_response)) { $return_val = null; } else { $return_val = $this->buildResult($method_response, $this->return_type); } $qn = new QName($this->methodname . 'Response', $this->method_namespace); $methodValue = new SOAP_Value($qn->fqn(), 'Struct', $return_val); } else { $methodValue =& $method_response; } return $this->makeEnvelope($methodValue, $header_results, $this->response_encoding); }
/** * Generates the complete XML SOAP message for an RPC call. * * @see call() * * @param string $method The method to call. * @param array $params The method parameters. * @param string|array $namespace Namespace or hash with options. Note: * most options need to be repeated for * SOAP_Value instances. * @param string $soapAction * * @return string The SOAP message including envelope. */ function _generate($method, $params, $namespace = false, $soapAction = false) { $this->fault = null; $this->_options['input'] = 'parse'; $this->_options['result'] = 'parse'; $this->_options['parameters'] = false; if ($params && !is_array($params)) { $params = array($params); } if (is_array($namespace)) { // Options passed as a hash. foreach ($namespace as $optname => $opt) { $this->_options[strtolower($optname)] = $opt; } } else { // We'll place $soapAction into our array for usage in the // transport. if ($soapAction) { $this->_options['soapaction'] = $soapAction; } if ($namespace) { $this->_options['namespace'] = $namespace; } } if (isset($this->_options['namespace'])) { $namespace = $this->_options['namespace']; } else { $namespace = false; } if ($this->_endpointType == 'wsdl') { $this->_setSchemaVersion($this->_wsdl->xsd); // Get port name. if (!$this->_portName) { $this->_portName = $this->_wsdl->getPortName($method); } if (PEAR::isError($this->_portName)) { return $this->_raiseSoapFault($this->_portName); } // Get endpoint. $this->_endpoint = $this->_wsdl->getEndpoint($this->_portName); if (PEAR::isError($this->_endpoint)) { return $this->_raiseSoapFault($this->_endpoint); } // Get operation data. $opData = $this->_wsdl->getOperationData($this->_portName, $method); if (PEAR::isError($opData)) { return $this->_raiseSoapFault($opData); } $namespace = isset($opData['namespace']) ? $opData['namespace'] : ''; $this->_options['style'] = $opData['style']; $this->_options['use'] = $opData['input']['use']; $this->_options['soapaction'] = $opData['soapAction']; // Set input parameters. if ($this->_options['input'] == 'parse') { $this->_options['parameters'] = $opData['parameters']; $nparams = array(); if (isset($opData['input']['parts']) && count($opData['input']['parts'])) { foreach ($opData['input']['parts'] as $name => $part) { $xmlns = ''; $attrs = array(); // Is the name a complex type? if (isset($part['element'])) { $xmlns = $this->_wsdl->namespaces[$part['namespace']]; $part = $this->_wsdl->elements[$part['namespace']][$part['type']]; $name = $part['name']; } if (isset($params[$name]) || $this->_wsdl->getDataHandler($name, $part['namespace'])) { $nparams[$name] =& $params[$name]; } else { // We now force an associative array for // parameters if using WSDL. return $this->_raiseSoapFault("The named parameter {$name} is not in the call parameters."); } if (gettype($nparams[$name]) != 'object' || !$nparams[$name] instanceof SOAP_Value) { // Type is likely a qname, split it apart, and get // the type namespace from WSDL. $qname = new QName($part['type']); if ($qname->ns) { $type_namespace = $this->_wsdl->namespaces[$qname->ns]; } elseif (isset($part['namespace'])) { $type_namespace = $this->_wsdl->namespaces[$part['namespace']]; } else { $type_namespace = null; } $qname->namespace = $type_namespace; $pqname = $name; if ($xmlns) { $pqname = '{' . $xmlns . '}' . $name; } $nparams[$name] = new SOAP_Value($pqname, $qname->fqn(), $nparams[$name], $attrs); } else { // WSDL fixups to the SOAP value. } } } $params =& $nparams; unset($nparams); } } else { $this->_setSchemaVersion(SOAP_XML_SCHEMA_VERSION); } // Serialize the message. $this->_section5 = !isset($this->_options['use']) || $this->_options['use'] != 'literal'; if (!isset($this->_options['style']) || $this->_options['style'] == 'rpc') { $this->_options['style'] = 'rpc'; $this->docparams = true; $mqname = new QName($method, $namespace); $methodValue = new SOAP_Value($mqname->fqn(), 'Struct', $params, array(), $this->_options); $soap_msg = $this->makeEnvelope($methodValue, $this->headersOut, $this->_encoding, $this->_options); } else { if (!$params) { $mqname = new QName($method, $namespace); $params = new SOAP_Value($mqname->fqn(), 'Struct', null); } elseif ($this->_options['input'] == 'parse') { if (is_array($params)) { $nparams = array(); $keys = array_keys($params); foreach ($keys as $k) { if (gettype($params[$k]) != 'object') { $nparams[] = new SOAP_Value($k, false, $params[$k]); } else { $nparams[] =& $params[$k]; } } $params =& $nparams; } if ($this->_options['parameters']) { $mqname = new QName($method, $namespace); $params = new SOAP_Value($mqname->fqn(), 'Struct', $params); } } $soap_msg = $this->makeEnvelope($params, $this->headersOut, $this->_encoding, $this->_options); } $this->headersOut = null; if (PEAR::isError($soap_msg)) { return $this->_raiseSoapFault($soap_msg); } // Handle MIME or DIME encoding. // TODO: DIME encoding should move to the transport, do it here for // now and for ease of getting it done. if (count($this->_attachments)) { if (isset($this->_options['attachments']) && $this->_options['attachments'] == 'Mime' || isset($this->_options['Mime'])) { $soap_msg = $this->_makeMimeMessage($soap_msg, $this->_encoding); } else { // default is dime $soap_msg = $this->_makeDIMEMessage($soap_msg, $this->_encoding); $this->_options['headers']['Content-Type'] = 'application/dime'; } if (PEAR::isError($soap_msg)) { return $this->_raiseSoapFault($soap_msg); } } // Instantiate client. if (is_array($soap_msg)) { $soap_data = $soap_msg['body']; if (count($soap_msg['headers'])) { if (isset($this->_options['headers'])) { $this->_options['headers'] = array_merge($this->_options['headers'], $soap_msg['headers']); } else { $this->_options['headers'] = $soap_msg['headers']; } } } else { $soap_data = $soap_msg; } return $soap_data; }