/** * SOAP_Client::call * * @param string method * @param array params * @param string namespace (not required if using wsdl) * @param string soapAction (not required if using wsdl) * * @return array of results * @access public */ function call($method, $params = array(), $namespace = false, $soapAction = false) { $this->fault = null; 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); } } $namespace = $this->wsdl->getNamespace($this->portName, $method); // get endpoint $this->endpoint = $this->wsdl->getEndpoint($this->portName); if (PEAR::isError($this->endpoint)) { return $this->raiseSoapFault($this->endpoint); } $this->debug("endpoint: {$this->endpoint}"); $this->debug("portName: {$this->portName}"); // get operation data $opData = $this->wsdl->getOperationData($this->portName, $method); if (PEAR::isError($opData)) { return $this->raiseSoapFault($opData); } $soapAction = $opData['soapAction']; // set input params $nparams = array(); if (count($opData['input']['parts']) > 0) { $i = 0; reset($params); foreach ($opData['input']['parts'] as $name => $type) { if (isset($params[$name])) { $nparams[$name] = $params[$name]; } else { // XXX assuming it's an array, not a hash // XXX this is pretty pethetic, but "fixes" a problem where // paremeter names do not match correctly $nparams[$name] = current($params); next($params); } if (gettype($nparams[$name]) != 'object' && get_class($nparams[$name]) != 'soap_value') { // type is a qname likely, split it apart, and get the type namespace from wsdl $qname = new QName($type); if ($qname->ns) { $type_namespace = $this->wsdl->namespaces[$qname->ns]; } else { $type_namespace = NULL; } $type = $qname->name; $nparams[$name] = new SOAP_Value($name, $type, $nparams[$name], $namespace, $type_namespace, $this->wsdl); } } } $params = $nparams; } $this->debug("soapAction: {$soapAction}"); $this->debug("namespace: {$namespace}"); // make message $soapmsg = new SOAP_Message($method, $params, $namespace, NULL, $this->wsdl); if ($soapmsg->fault) { return $this->raiseSoapFault($soapmsg->fault); } // serialize the message $soap_data = $soapmsg->serialize(); $this->debug("soap_data " . $soap_data); if (PEAR::isError($soap_data)) { return $this->raiseSoapFault($soap_data); } $this->debug('<xmp>' . $soap_data . '</xmp>'); // instantiate client $dbg = "calling server at '{$this->endpoint}'..."; $soap_transport = new SOAP_Transport($this->endpoint, $this->debug_flag); if ($soap_transport->fault) { return $this->raiseSoapFault($soap_transport->fault); } $this->debug($dbg . 'instantiated client successfully'); $this->debug("endpoint: {$this->endpoint}<br>\n"); // send $dbg = "sending msg w/ soapaction '{$soapAction}'..."; // send the message $this->response = $soap_transport->send($soap_data, $soapAction); if ($soap_transport->fault) { return $this->raiseSoapFault($this->response); } // parse the response $return = $soapmsg->parseResponse($this->response); $this->debug($soap_transport->debug_data); $this->debug($dbg . 'sent message successfully and got a(n) ' . gettype($return) . ' back'); // check for valid response if (PEAR::isError($return)) { return $this->raiseSoapFault($return); } else { if (strcasecmp(get_class($return), 'SOAP_Value') != 0) { return $this->raiseSoapFault("didn't get SOAP_Value object back from client"); } } // decode to native php datatype $returnArray = $return->decode(); // fault? if (PEAR::isError($returnArray)) { return $this->raiseSoapFault($returnArray); } if (is_array($returnArray)) { if (isset($returnArray['faultcode']) || isset($returnArray['SOAP-ENV:faultcode'])) { foreach ($returnArray as $k => $v) { if (stristr($k, 'faultcode')) { $this->faultcode = $v; } if (stristr($k, 'faultstring')) { $this->faultstring = $v; } if (stristr($k, 'faultdetail')) { $this->faultdetail = $v; } if (stristr($k, 'faultactor')) { $this->faultactor = $v; } } return $this->raiseSoapFault($this->faultstring, $this->faultdetail, $this->faultactor, $this->faultcode); } // return array of return values if (count($returnArray) == 1) { return array_shift($returnArray); } return $returnArray; } return $returnArray; }
/** * send and receive soap data * * @param string &$msg outgoing post data * @param string $action SOAP Action header data * @param int $timeout socket timeout, default 0 or off * * @return string &$response response data, minus http headers * @access public */ function send(&$msg, $action = '', $timeout = 0) { if (!$this->_validateUrl()) { return $this->raiseSoapFault($this->errmsg); } $headers = "From: {$action}\n" . "X-Mailer: {$this->_userAgent}\n" . "MIME-Version: 1.0\n" . "Content-Type: text/xml; charset=\"utf-8\"\n" . "Content-Transfer-Encoding: quoted-printable\n"; $subject = 'SOAP Message'; # we want to return a proper XML message $result = mail($this->urlparts['path'], $subject, $msg, $headers); if ($result) { $val = new SOAP_Value('return', 'boolean', TRUE); } else { $val = new SOAP_Value('Fault', 'struct', array(new SOAP_Value('faultcode', 'string', 'SOAP-ENV:Transport:SMTP'), new SOAP_Value('faultstring', 'string', "couldn't send message to {$action}"))); } $return_msg = new SOAP_Message('Response', array($val), 'smtp'); $response = $return_msg->serialize(); return $result; }