Source for file Client.php
Documentation is available at Client.php
// +----------------------------------------------------------------------+
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more |
// | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author |
// +----------------------------------------------------------------------+
// $Id: Client.php,v 1.73 2005/05/28 17:36:41 yunosh Exp $
require_once 'SOAP/Value.php';
require_once 'SOAP/Base.php';
require_once 'SOAP/Transport.php';
require_once 'SOAP/WSDL.php';
require_once 'SOAP/Fault.php';
require_once 'SOAP/Parser.php';
// Arnaud: the following code was taken from DataObject and adapted to suit
// this will be horrifically slow!!!!
// NOTE: Overload SEGFAULTS ON PHP4 + Zend Optimizer
// these two are BC/FC handlers for call in PHP4/5
function __call($method, $args)
$this->_call ($method, $args, $return);
eval ('function clone($t) { return $t; }');
class SOAP_Client_Overload extends SOAP_Base {
function __call($method, $args, &$return)
return $this->_call($method, $args, $return);
* This class is the main interface for making soap requests.
* $soapclient = new SOAP_Client( string path [ , boolean wsdl] );
* echo $soapclient->call( string methodname [ , array parameters] );
* Originally based on SOAPx4 by Dietrich Ayala
* http://dietrich.ganx4.com/soapx4
* @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates
* @author Stig Bakken <ssb@fast.no> Conversion to PEAR
* @author Dietrich Ayala <dietrich@ganx4.com> Original Author
* Communication endpoint.
* Currently the following transport formats are supported:
* http://www.example.com/soap/server.php
* https://www.example.com/soap/server.php
* mailto:soap@example.com
* The SOAP PORT name that is used by the client.
* Endpoint type e.g. 'wdsl'.
* @var $__endpointType string
var $__endpointType = '';
* The outgoing and incoming data stream for debugging.
var $__last_request = null;
var $__last_response = null;
var $__options = array ('trace'=>0 );
* The character encoding used for XML parser, etc.
var $_encoding = SOAP_DEFAULT_ENCODING;
* The array of SOAP_Headers that we are sending.
* The headers we recieved back in the response.
* Options for the HTTP_Request class (see HTTP/Request.php).
* @var $__proxy_params array
var $__proxy_params = array ();
var $_soap_transport = null;
* @param string $endpoint An URL.
* @param boolean $wsdl Whether the endpoint is a WSDL file.
* @param string $portName
* @param array $proxy_params Options for the HTTP_Request class (see
function SOAP_Client($endpoint, $wsdl = false , $portName = false ,
parent ::SOAP_Base ('Client');
$this->_endpoint = $endpoint;
$this->_portName = $portName;
$this->__proxy_params = $proxy_params;
// This hack should perhaps be removed as it might cause unexpected
$this->__endpointType = 'wsdl';
// instantiate wsdl class
$this->_wsdl = & new SOAP_WSDL($this->_endpoint,
if ($this->_wsdl->fault ) {
$this->_raiseSoapFault ($this->_wsdl->fault );
$this->__last_request = null;
$this->__last_response = null;
* Sets the character encoding.
* Limited to 'UTF-8', 'US_ASCII' and 'ISO-8859-1'.
* @return mixed SOAP_Fault on error.
if (in_array($encoding, $this->_encodings)) {
$this->_encoding = $encoding;
return $this->_raiseSoapFault ('Invalid Encoding');
* Adds a header to the envelope.
* @param SOAP_Header $soap_value A SOAP_Header or an array with the
* elements 'name', 'namespace',
* 'mustunderstand', and 'actor' to send
// Add a new header to the message.
if (is_a($soap_value, 'SOAP_Header')) {
// name, value, namespace, mustunderstand, actor
$this->_raiseSoapFault ('Invalid parameter provided to addHeader(). Must be an array or a SOAP_Header.');
* Calls a method on the SOAP endpoint.
* The namespace parameter is overloaded to accept an array of options
* that can contain data necessary for various transports if it is used as
* an array, it MAY contain a namespace value and a soapaction value. If
* it is overloaded, the soapaction parameter is ignored and MUST be
* placed in the options array. This is done to provide backwards
* compatibility with current clients, but may be removed in the future.
* The currently supported values are:<pre>
* timeout (HTTP socket timeout)
* transfer-encoding (SMTP, Content-Transfer-Encoding: header)
* from (SMTP, From: header)
* subject (SMTP, Subject: header)
* headers (SMTP, hash of extra SMTP headers)
* @param string $method The method to call.
* @param array $params The method parameters.
* @param string|array$namespace Namespace or hash with options.
* @param string $soapAction
* @return mixed The method result or a SOAP_Fault on error.
function &call($method, &$params, $namespace = false , $soapAction = false )
$this->__last_request = null;
$this->__last_response = null;
$soap_data = & $this->__generate($method, $params, $namespace, $soapAction);
if (PEAR ::isError ($soap_data)) {
return $this->_raiseSoapFault ($soap_data);
// __generate() may have changed the endpoint if the WSDL has more
// than one service, so we need to see if we need to generate a new
// transport to hook to a different URI. Since the transport protocol
// can also change, we need to get an entirely new object. This could
// probably be optimized.
if (!$this->_soap_transport ||
$this->_endpoint != $this->_soap_transport->url ) {
if (PEAR ::isError ($this->_soap_transport)) {
$fault = & $this->_soap_transport;
$this->_soap_transport = null;
return $this->_raiseSoapFault ($fault);
$this->_soap_transport->encoding = $this->_encoding;
$this->xml = & $this->_soap_transport->send ($soap_data, $transport_options);
// Save the wire information for debugging.
if ($this->__options['trace'] > 0 ) {
$this->__last_request = & $this->_soap_transport->outgoing_payload;
$this->__last_response = & $this->_soap_transport->incoming_payload;
if ($this->_soap_transport->fault ) {
return $this->_raiseSoapFault ($this->xml);
$this->__attachments = & $this->_soap_transport->attachments;
$this->__result_encoding = $this->_soap_transport->result_encoding;
if (isset ($this->__options['result']) &&
$this->__options['result'] != 'parse') {
return $this->__parse($this->xml, $this->__result_encoding, $this->__attachments);
* Sets an option to use with the transport layers.
* $soapclient->setOpt('curl', CURLOPT_VERBOSE, 1)
* to pass a specific option to curl if using an SSL connection.
* @param string $category Category to which the option applies or option
* @param string $option An option name if $category is a category name,
* an option value if $category is an option name.
* @param string $value An option value if $category is a category
function setOpt($category, $option, $value = null )
if (!isset ($this->__options[$category])) {
$this->__options[$category] = array ();
$this->__options[$category][$option] = $value;
$this->__options[$category] = $option;
* Call method supporting the overload extension.
* If the overload extension is loaded, you can call the client class with
* $soap = new SOAP_Client(....);
* $value = $soap->getStockQuote('MSFT');
* @param string $method The method to call.
* @param array $params The method parameters.
* @param string $return_value Will get the method's return value
* @return boolean Always true.
function _call($method, $params, &$return_value)
// Overloading lowercases the method name, we need to look into the
// wsdl and try to find the correct method name to get the correct
$this->_wsdl->matchMethod ($method);
$return_value = & $this->call($method, $params);
return $this->__last_request;
return $this->__last_response;
$this->__options['use'] = $use;
$this->__options['style'] = $style;
$this->__options['trace'] = $level;
function &__generate($method, &$params, $namespace = false ,
$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) {
if (isset ($this->__options['namespace'])) {
$namespace = $this->__options['namespace'];
// We'll place $soapAction into our array for usage in the
$this->__options['soapaction'] = $soapAction;
$this->__options['namespace'] = $namespace;
if ($this->__endpointType == 'wsdl') {
$this->_setSchemaVersion ($this->_wsdl->xsd );
$this->_portName = $this->_wsdl->getPortName ($method);
if (PEAR ::isError ($this->_portName)) {
return $this->_raiseSoapFault ($this->_portName);
$this->_endpoint = $this->_wsdl->getEndpoint ($this->_portName);
if (PEAR ::isError ($this->_endpoint)) {
return $this->_raiseSoapFault ($this->_endpoint);
$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'];
if ($this->__options['input'] == 'parse') {
$this->__options['parameters'] = $opData['parameters'];
if (isset ($opData['input']['parts']) &&
count($opData['input']['parts'])) {
foreach ($opData['input']['parts'] as $name => $part) {
// Is the name a complex type?
if (isset ($part['element'])) {
$xmlns = $this->_wsdl->namespaces [$part['namespace']];
$part = $this->_wsdl->elements [$part['namespace']][$part['type']];
if (isset ($params[$name]) ||
$this->_wsdl->getDataHandler ($name, $part['namespace'])) {
$nparams[$name] = & $params[$name];
// 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 likely a qname, split it apart, and get
// the type namespace from WSDL.
$qname = & new QName($part['type']);
$type_namespace = $this->_wsdl->namespaces [$qname->ns ];
} elseif (isset ($part['namespace'])) {
$type_namespace = $this->_wsdl->namespaces [$part['namespace']];
$qname->namespace = $type_namespace;
$pqname = '{' . $xmlns . '}' . $name;
// WSDL fixups to the SOAP value.
// 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';
$mqname = & new QName($method, $namespace);
$methodValue = & new SOAP_Value($mqname->fqn (), 'Struct', $params);
$soap_msg = & $this->_makeEnvelope ($methodValue,
$mqname = & new QName($method, $namespace);
$params = & new SOAP_Value($mqname->fqn (), 'Struct', $mynull);
} elseif ($this->__options['input'] == 'parse') {
if (gettype($params[$k]) != 'object') {
$nparams[] = & $params[$k];
if ($this->__options['parameters']) {
$mqname = & new QName($method, $namespace);
$soap_msg = & $this->_makeEnvelope ($params,
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,
$soap_msg = & $this->_makeDIMEMessage ($soap_msg,
$this->__options['headers']['Content-Type'] = 'application/dime';
if (PEAR ::isError ($soap_msg)) {
return $this->_raiseSoapFault ($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']);
$this->__options['headers'] = $soap_msg['headers'];
function &__parse(&$response, $encoding, &$attachments)
$response = & new SOAP_Parser($response, $encoding, $attachments);
return $this->_raiseSoapFault ($response->fault );
// Return array of parameters.
$return = & $response->getResponse ();
$headers = & $response->getHeaders ();
// Check for valid response.
if (PEAR ::isError ($response)) {
return $this->_raiseSoapFault ($response);
} elseif (!is_a($response, 'soap_value')) {
return $this->_raiseSoapFault ("Didn't get SOAP_Value object back from client");
// Decode to native php datatype.
$returnArray = & $this->_decode ($response);
if (PEAR ::isError ($returnArray)) {
return $this->_raiseSoapFault ($returnArray);
if (isset ($returnArray['faultcode']) ||
isset ($returnArray['SOAP-ENV:faultcode'])) {
$faultcode = $faultstring = $faultdetail = $faultactor = '';
foreach ($returnArray as $k => $v) {
if (stristr($k, 'faultcode')) $faultcode = $v;
if (stristr($k, 'faultstring')) $faultstring = $v;
if (stristr($k, 'detail')) $faultdetail = $v;
if (stristr($k, 'faultactor')) $faultactor = $v;
return $this->_raiseSoapFault ($faultstring, $faultdetail, $faultactor, $faultcode);
// Return array of return values.
if ($shift && count($returnArray) == 1 ) {
if ($this->__options['trace'] > 0 &&
($this->__last_request || $this->__last_response)) {
Documentation generated on Mon, 11 Mar 2019 14:20:02 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|