SOAP
[ class tree: SOAP ] [ index: SOAP ] [ all elements ]

Source for file Client.php

Documentation is available at Client.php

  1. <?php
  2. /**
  3.  * This file contains the code for the SOAP client.
  4.  *
  5.  * PHP versions 4 and 5
  6.  *
  7.  * LICENSE: This source file is subject to version 2.02 of the PHP license,
  8.  * that is bundled with this package in the file LICENSE, and is available at
  9.  * through the world-wide-web at http://www.php.net/license/2_02.txt.  If you
  10.  * did not receive a copy of the PHP license and are unable to obtain it
  11.  * through the world-wide-web, please send a note to license@php.net so we can
  12.  * mail you a copy immediately.
  13.  *
  14.  * @category   Web Services
  15.  * @package    SOAP
  16.  * @author     Dietrich Ayala <dietrich@ganx4.com> Original Author
  17.  * @author     Shane Caraveo <Shane@Caraveo.com>   Port to PEAR and more
  18.  * @author     Chuck Hagenbuch <chuck@horde.org>   Maintenance
  19.  * @author     Jan Schneider <jan@horde.org>       Maintenance
  20.  * @copyright  2003-2005 The PHP Group
  21.  * @license    http://www.php.net/license/2_02.txt  PHP License 2.02
  22.  * @link       http://pear.php.net/package/SOAP
  23.  */
  24.  
  25. /** SOAP_Value */
  26. require_once 'SOAP/Value.php';
  27. require_once 'SOAP/Base.php';
  28. require_once 'SOAP/Transport.php';
  29. require_once 'SOAP/WSDL.php';
  30. require_once 'SOAP/Fault.php';
  31. require_once 'SOAP/Parser.php';
  32.  
  33. // Arnaud: the following code was taken from DataObject and adapted to suit
  34.  
  35. // this will be horrifically slow!!!!
  36. // NOTE: Overload SEGFAULTS ON PHP4 + Zend Optimizer
  37. // these two are BC/FC handlers for call in PHP4/5
  38.  
  39. /**
  40.  * @package SOAP
  41.  */
  42. if (!class_exists('SOAP_Client_Overload')) {
  43.     if (substr(zend_version()01> 1{
  44.         class SOAP_Client_Overload extends SOAP_Base {
  45.             function __call($method$args)
  46.             {
  47.                 $return = null;
  48.                 $this->_call($method$args$return);
  49.                 return $return;
  50.             }
  51.         }
  52.     else {
  53.         if (!function_exists('clone')) {
  54.             eval('function clone($t) { return $t; }');
  55.         }
  56.         eval('
  57.             class SOAP_Client_Overload extends SOAP_Base {
  58.                 function __call($method, $args, &$return)
  59.                 {
  60.                     return $this->_call($method, $args, $return);
  61.                 }
  62.             }');
  63.     }
  64. }
  65.  
  66. /**
  67.  * SOAP Client Class
  68.  *
  69.  * This class is the main interface for making soap requests.
  70.  *
  71.  * basic usage:<code>
  72.  *   $soapclient = new SOAP_Client( string path [ , boolean wsdl] );
  73.  *   echo $soapclient->call( string methodname [ , array parameters] );
  74.  * </code>
  75.  * or, if using PHP 5+ or the overload extension:<code>
  76.  *   $soapclient = new SOAP_Client( string path [ , boolean wsdl] );
  77.  *   echo $soapclient->methodname( [ array parameters] );
  78.  * </code>
  79.  *
  80.  * Originally based on SOAPx4 by Dietrich Ayala
  81.  * http://dietrich.ganx4.com/soapx4
  82.  *
  83.  * @access   public
  84.  * @package  SOAP
  85.  * @author   Shane Caraveo <shane@php.net> Conversion to PEAR and updates
  86.  * @author   Stig Bakken <ssb@fast.no> Conversion to PEAR
  87.  * @author   Dietrich Ayala <dietrich@ganx4.com> Original Author
  88.  */
  89. {
  90.     /**
  91.      * Communication endpoint.
  92.      *
  93.      * Currently the following transport formats are supported:
  94.      *  - HTTP
  95.      *  - SMTP
  96.      *
  97.      * Example endpoints:
  98.      *   http://www.example.com/soap/server.php
  99.      *   https://www.example.com/soap/server.php
  100.      *   mailto:soap@example.com
  101.      *
  102.      * @see SOAP_Client()
  103.      * @var string 
  104.      */
  105.     var $_endpoint '';
  106.  
  107.     /**
  108.      * The SOAP PORT name that is used by the client.
  109.      *
  110.      * @var string 
  111.      */
  112.     var $_portName '';
  113.  
  114.     /**
  115.      * Endpoint type e.g. 'wdsl'.
  116.      *
  117.      * @var string 
  118.      */
  119.     var $_endpointType '';
  120.  
  121.     /**
  122.      * The received xml.
  123.      *
  124.      * @var string 
  125.      */
  126.     var $xml;
  127.  
  128.     /**
  129.      * The outgoing and incoming data stream for debugging.
  130.      *
  131.      * @var string 
  132.      */
  133.     var $wire;
  134.  
  135.     /**
  136.      * The outgoing data stream for debugging.
  137.      *
  138.      * @var string 
  139.      */
  140.     var $_last_request = null;
  141.  
  142.     /**
  143.      * The incoming data stream for debugging.
  144.      *
  145.      * @var string 
  146.      */
  147.     var $_last_response = null;
  148.  
  149.     /**
  150.      * Options.
  151.      *
  152.      * @var array 
  153.      */
  154.     var $_options = array('trace' => false);
  155.  
  156.     /**
  157.      * The character encoding used for XML parser, etc.
  158.      *
  159.      * @var string 
  160.      */
  161.     var $_encoding = SOAP_DEFAULT_ENCODING;
  162.  
  163.     /**
  164.      * The array of SOAP_Headers that we are sending.
  165.      *
  166.      * @var array 
  167.      */
  168.     var $headersOut = null;
  169.  
  170.     /**
  171.      * The headers we recieved back in the response.
  172.      *
  173.      * @var array 
  174.      */
  175.     var $headersIn = null;
  176.  
  177.     /**
  178.      * Options for the HTTP_Request class (see HTTP/Request.php).
  179.      *
  180.      * @var array 
  181.      */
  182.     var $_proxy_params = array();
  183.  
  184.     /**
  185.      * The SOAP_Transport instance.
  186.      *
  187.      * @var SOAP_Transport 
  188.      */
  189.     var $_soap_transport = null;
  190.  
  191.     /**
  192.      * Constructor.
  193.      *
  194.      * @access public
  195.      *
  196.      * @param string $endpoint       An URL.
  197.      * @param boolean $wsdl          Whether the endpoint is a WSDL file.
  198.      * @param string $portName       The service's port name to use.
  199.      * @param array $proxy_params    Options for the HTTP_Request class
  200.      *                               @see HTTP_Request
  201.      * @param boolean|string$cache  Use WSDL caching? The cache directory if
  202.      *                                a string.
  203.      */
  204.     function SOAP_Client($endpoint$wsdl = false$portName = false,
  205.                          $proxy_params = array()$cache = false)
  206.     {
  207.         parent::SOAP_Base('Client');
  208.  
  209.         $this->_endpoint $endpoint;
  210.         $this->_portName $portName;
  211.         $this->_proxy_params $proxy_params;
  212.  
  213.         // This hack should perhaps be removed as it might cause unexpected
  214.         // behaviour.
  215.         $wsdl $wsdl
  216.             ? $wsdl
  217.             : strtolower(substr($endpoint-4)) == 'wsdl';
  218.  
  219.         // make values
  220.         if ($wsdl{
  221.             $this->_endpointType 'wsdl';
  222.             // instantiate wsdl class
  223.             $this->_wsdl = new SOAP_WSDL($this->_endpoint,
  224.                                          $this->_proxy_params,
  225.                                          $cache);
  226.             if ($this->_wsdl->fault{
  227.                 $this->_raiseSoapFault($this->_wsdl->fault);
  228.             }
  229.         }
  230.     }
  231.  
  232.     function _reset()
  233.     {
  234.         $this->xml = null;
  235.         $this->wire = null;
  236.         $this->_last_request = null;
  237.         $this->_last_response = null;
  238.         $this->headersIn = null;
  239.         $this->headersOut = null;
  240.     }
  241.  
  242.     /**
  243.      * Sets the character encoding.
  244.      *
  245.      * Limited to 'UTF-8', 'US_ASCII' and 'ISO-8859-1'.
  246.      *
  247.      * @access public
  248.      *
  249.      * @param string encoding
  250.      *
  251.      * @return mixed  SOAP_Fault on error.
  252.      */
  253.     function setEncoding($encoding)
  254.     {
  255.         if (in_array($encoding$this->_encodings)) {
  256.             $this->_encoding $encoding;
  257.             return;
  258.         }
  259.         return $this->_raiseSoapFault('Invalid Encoding');
  260.     }
  261.  
  262.     /**
  263.      * Adds a header to the envelope.
  264.      *
  265.      * @access public
  266.      *
  267.      * @param SOAP_Header $soap_value  A SOAP_Header or an array with the
  268.      *                                  elements 'name', 'namespace',
  269.      *                                  'mustunderstand', and 'actor' to send
  270.      *                                  as a header.
  271.      */
  272.     function addHeader($soap_value)
  273.     {
  274.         // Add a new header to the message.
  275.         if (is_a($soap_value'SOAP_Header')) {
  276.             $this->headersOut[$soap_value;
  277.         elseif (is_array($soap_value)) {
  278.             // name, value, namespace, mustunderstand, actor
  279.             $this->headersOut[= new SOAP_Header($soap_value[0],
  280.                                                   null,
  281.                                                   $soap_value[1],
  282.                                                   $soap_value[2],
  283.                                                   $soap_value[3]);
  284.         else {
  285.             $this->_raiseSoapFault('Invalid parameter provided to addHeader().  Must be an array or a SOAP_Header.');
  286.         }
  287.     }
  288.  
  289.     /**
  290.      * Calls a method on the SOAP endpoint.
  291.      *
  292.      * The namespace parameter is overloaded to accept an array of options
  293.      * that can contain data necessary for various transports if it is used as
  294.      * an array, it MAY contain a namespace value and a soapaction value.  If
  295.      * it is overloaded, the soapaction parameter is ignored and MUST be
  296.      * placed in the options array.  This is done to provide backwards
  297.      * compatibility with current clients, but may be removed in the future.
  298.      * The currently supported values are:
  299.      * - 'namespace'
  300.      * - 'soapaction'
  301.      * - 'timeout': HTTP socket timeout
  302.      * - 'transfer-encoding': SMTP transport, Content-Transfer-Encoding: header
  303.      * - 'from': SMTP transport, From: header
  304.      * - 'subject': SMTP transport, Subject: header
  305.      * - 'headers': SMTP transport, hash of extra SMTP headers
  306.      * - 'attachments': what encoding to use for attachments (Mime, Dime)
  307.      * - 'trace': whether to trace the SOAP communication
  308.      * - 'style': 'document' or 'rpc'; when set to 'document' the parameters
  309.      *   are not wrapped inside a tag with the SOAP action name
  310.      * - 'use': 'literal' for literal encoding, anything else for section 5
  311.      *   encoding; when set to 'literal' SOAP types will be omitted.
  312.      * - 'keep_arrays_flat': use the tag name multiple times for each element
  313.      *   when passing in an array in literal mode
  314.      * - 'no_type_prefix': supress adding of the namespace prefix
  315.      *
  316.      * @access public
  317.      *
  318.      * @param string $method           The method to call.
  319.      * @param array $params            The method parameters.
  320.      * @param string|array$namespace  Namespace or hash with options. Note:
  321.      *                                  most options need to be repeated for
  322.      *                                  SOAP_Value instances.
  323.      * @param string $soapAction 
  324.      *
  325.      * @return mixed  The method result or a SOAP_Fault on error.
  326.      */
  327.     function call($method$params$namespace = false$soapAction = false)
  328.     {
  329.         $this->headersIn = null;
  330.         $this->_last_request = null;
  331.         $this->_last_response = null;
  332.         $this->wire = null;
  333.         $this->xml = null;
  334.  
  335.         $soap_data $this->_generate($method$params$namespace$soapAction);
  336.         if (PEAR::isError($soap_data)) {
  337.             $fault $this->_raiseSoapFault($soap_data);
  338.             return $fault;
  339.         }
  340.  
  341.         // _generate() may have changed the endpoint if the WSDL has more
  342.         // than one service, so we need to see if we need to generate a new
  343.         // transport to hook to a different URI.  Since the transport protocol
  344.         // can also change, we need to get an entirely new object.  This could
  345.         // probably be optimized.
  346.         if (!$this->_soap_transport ||
  347.             $this->_endpoint != $this->_soap_transport->url{
  348.             $this->_soap_transport SOAP_Transport::getTransport($this->_endpoint);
  349.             if (PEAR::isError($this->_soap_transport)) {
  350.                 $fault $this->_raiseSoapFault($this->_soap_transport);
  351.                 $this->_soap_transport = null;
  352.                 return $fault;
  353.             }
  354.         }
  355.         $this->_soap_transport->encoding = $this->_encoding;
  356.  
  357.         // Send the message.
  358.         $transport_options array_merge_recursive($this->_proxy_params,
  359.                                                    $this->_options);
  360.         $this->xml = $this->_soap_transport->send($soap_data$transport_options);
  361.  
  362.         // Save the wire information for debugging.
  363.         if ($this->_options['trace']{
  364.             $this->_last_request $this->_soap_transport->outgoing_payload;
  365.             $this->_last_response $this->_soap_transport->incoming_payload;
  366.             $this->wire = $this->getWire();
  367.         }
  368.         if ($this->_soap_transport->fault{
  369.             $fault $this->_raiseSoapFault($this->xml);
  370.             return $fault;
  371.         }
  372.  
  373.         if (isset($this->_options['result']&&
  374.             $this->_options['result'!= 'parse'{
  375.             return $this->xml;
  376.         }
  377.  
  378.         $this->__result_encoding $this->_soap_transport->result_encoding;
  379.  
  380.         $result $this->parseResponse($this->xml$this->__result_encoding,
  381.                                        $this->_soap_transport->attachments);
  382.         return $result;
  383.     }
  384.  
  385.     /**
  386.      * Sets an option to use with the transport layers.
  387.      *
  388.      * For example:
  389.      * <code>
  390.      * $soapclient->setOpt('curl', CURLOPT_VERBOSE, 1)
  391.      * </code>
  392.      * to pass a specific option to curl if using an SSL connection.
  393.      *
  394.      * @access public
  395.      *
  396.      * @param string $category  Category to which the option applies or option
  397.      *                           name.
  398.      * @param string $option    An option name if $category is a category name,
  399.      *                           an option value if $category is an option name.
  400.      * @param string $value     An option value if $category is a category
  401.      *                           name.
  402.      */
  403.     function setOpt($category$option$value = null)
  404.     {
  405.         if (!is_null($value)) {
  406.             if (!isset($this->_options[$category])) {
  407.                 $this->_options[$category= array();
  408.             }
  409.             $this->_options[$category][$option$value;
  410.         else {
  411.             $this->_options[$category$option;
  412.         }
  413.     }
  414.  
  415.     /**
  416.      * Call method supporting the overload extension.
  417.      *
  418.      * If the overload extension is loaded, you can call the client class with
  419.      * a soap method name:
  420.      * <code>
  421.      * $soap = new SOAP_Client(....);
  422.      * $value = $soap->getStockQuote('MSFT');
  423.      * </code>
  424.      *
  425.      * @access public
  426.      *
  427.      * @param string $method        The method to call.
  428.      * @param array $params         The method parameters.
  429.      * @param mixed $return_value   Will get the method's return value
  430.      *                               assigned.
  431.      *
  432.      * @return boolean  Always true.
  433.      */
  434.     function _call($method$params&$return_value)
  435.     {
  436.         // Overloading lowercases the method name, we need to look into the
  437.         // WSDL and try to find the correct method name to get the correct
  438.         // case for the call.
  439.         if ($this->_wsdl{
  440.             $this->_wsdl->matchMethod($method);
  441.         }
  442.  
  443.         $return_value $this->call($method$params);
  444.  
  445.         return true;
  446.     }
  447.  
  448.     /**
  449.      * Returns the XML content of the last SOAP request.
  450.      *
  451.      * @return string  The last request.
  452.      */
  453.     function getLastRequest()
  454.     {
  455.         return $this->_last_request;
  456.     }
  457.  
  458.     /**
  459.      * Returns the XML content of the last SOAP response.
  460.      *
  461.      * @return string  The last response.
  462.      */
  463.     function getLastResponse()
  464.     {
  465.         return $this->_last_response;
  466.     }
  467.  
  468.     /**
  469.      * Sets the SOAP encoding.
  470.      *
  471.      * The default encoding is section 5 encoded.
  472.      *
  473.      * @param string $use  Either 'literal' or 'encoded' (section 5).
  474.      */
  475.     function setUse($use)
  476.     {
  477.         $this->_options['use'$use;
  478.     }
  479.  
  480.     /**
  481.      * Sets the SOAP encoding style.
  482.      *
  483.      * The default style is rpc.
  484.      *
  485.      * @param string $style  Either 'document' or 'rpc'.
  486.      */
  487.     function setStyle($style)
  488.     {
  489.         $this->_options['style'$style;
  490.     }
  491.  
  492.     /**
  493.      * Sets whether to trace the traffic on the transport level.
  494.      *
  495.      * @see getWire()
  496.      *
  497.      * @param boolean $trace 
  498.      */
  499.     function setTrace($trace)
  500.     {
  501.         $this->_options['trace'$trace;
  502.     }
  503.  
  504.     /**
  505.      * Generates the complete XML SOAP message for an RPC call.
  506.      *
  507.      * @see call()
  508.      *
  509.      * @param string $method           The method to call.
  510.      * @param array $params            The method parameters.
  511.      * @param string|array$namespace  Namespace or hash with options. Note:
  512.      *                                  most options need to be repeated for
  513.      *                                  SOAP_Value instances.
  514.      * @param string $soapAction 
  515.      *
  516.      * @return string  The SOAP message including envelope.
  517.      */
  518.     function _generate($method$params$namespace = false,
  519.                        $soapAction = false)
  520.     {
  521.         $this->fault = null;
  522.         $this->_options['input''parse';
  523.         $this->_options['result''parse';
  524.         $this->_options['parameters'= false;
  525.  
  526.         if ($params && !is_array($params)) {
  527.             $params = array($params);
  528.         }
  529.  
  530.         if (is_array($namespace)) {
  531.             // Options passed as a hash.
  532.             foreach ($namespace as $optname => $opt{
  533.                 $this->_options[strtolower($optname)$opt;
  534.             }
  535.         else {
  536.             // We'll place $soapAction into our array for usage in the
  537.             // transport.
  538.             if ($soapAction{
  539.                 $this->_options['soapaction'$soapAction;
  540.             }
  541.             if ($namespace{
  542.                 $this->_options['namespace'$namespace;
  543.             }
  544.         }
  545.         if (isset($this->_options['namespace'])) {
  546.             $namespace $this->_options['namespace'];
  547.         else {
  548.             $namespace = false;
  549.         }
  550.  
  551.         if ($this->_endpointType == 'wsdl'{
  552.             $this->_setSchemaVersion($this->_wsdl->xsd);
  553.  
  554.             // Get port name.
  555.             if (!$this->_portName{
  556.                 $this->_portName $this->_wsdl->getPortName($method);
  557.             }
  558.             if (PEAR::isError($this->_portName)) {
  559.                 return $this->_raiseSoapFault($this->_portName);
  560.             }
  561.  
  562.             // Get endpoint.
  563.             $this->_endpoint $this->_wsdl->getEndpoint($this->_portName);
  564.             if (PEAR::isError($this->_endpoint)) {
  565.                 return $this->_raiseSoapFault($this->_endpoint);
  566.             }
  567.  
  568.             // Get operation data.
  569.             $opData $this->_wsdl->getOperationData($this->_portName$method);
  570.  
  571.             if (PEAR::isError($opData)) {
  572.                 return $this->_raiseSoapFault($opData);
  573.             }
  574.             $namespace                    $opData['namespace'];
  575.             $this->_options['style']      $opData['style'];
  576.             $this->_options['use']        $opData['input']['use'];
  577.             $this->_options['soapaction'$opData['soapAction'];
  578.  
  579.             // Set input parameters.
  580.             if ($this->_options['input'== 'parse'{
  581.                 $this->_options['parameters'$opData['parameters'];
  582.                 $nparams = array();
  583.                 if (isset($opData['input']['parts']&&
  584.                     count($opData['input']['parts'])) {
  585.                     foreach ($opData['input']['parts'as $name => $part{
  586.                         $xmlns '';
  587.                         $attrs = array();
  588.                         // Is the name a complex type?
  589.                         if (isset($part['element'])) {
  590.                             $xmlns $this->_wsdl->namespaces[$part['namespace']];
  591.                             $part $this->_wsdl->elements[$part['namespace']][$part['type']];
  592.                             $name $part['name'];
  593.                         }
  594.                         if (isset($params[$name]||
  595.                             $this->_wsdl->getDataHandler($name$part['namespace'])) {
  596.                             $nparams[$name=$params[$name];
  597.                         else {
  598.                             // We now force an associative array for
  599.                             // parameters if using WSDL.
  600.                             return $this->_raiseSoapFault("The named parameter $name is not in the call parameters.");
  601.                         }
  602.                         if (gettype($nparams[$name]!= 'object' ||
  603.                             !is_a($nparams[$name]'SOAP_Value')) {
  604.                             // Type is likely a qname, split it apart, and get
  605.                             // the type namespace from WSDL.
  606.                             $qname = new QName($part['type']);
  607.                             if ($qname->ns{
  608.                                 $type_namespace $this->_wsdl->namespaces[$qname->ns];
  609.                             elseif (isset($part['namespace'])) {
  610.                                 $type_namespace $this->_wsdl->namespaces[$part['namespace']];
  611.                             else {
  612.                                 $type_namespace = null;
  613.                             }
  614.                             $qname->namespace = $type_namespace;
  615.                             $pqname $name;
  616.                             if ($xmlns{
  617.                                 $pqname '{' $xmlns '}' $name;
  618.                             }
  619.                             $nparams[$name= new SOAP_Value($pqname,
  620.                                                               $qname->fqn(),
  621.                                                               $nparams[$name],
  622.                                                               $attrs);
  623.                         else {
  624.                             // WSDL fixups to the SOAP value.
  625.                         }
  626.                     }
  627.                 }
  628.                 $params =$nparams;
  629.                 unset($nparams);
  630.             }
  631.         else {
  632.             $this->_setSchemaVersion(SOAP_XML_SCHEMA_VERSION);
  633.         }
  634.  
  635.         // Serialize the message.
  636.         $this->_section5 (!isset($this->_options['use']||
  637.                             $this->_options['use'!= 'literal');
  638.  
  639.         if (!isset($this->_options['style']||
  640.             $this->_options['style'== 'rpc'{
  641.             $this->_options['style''rpc';
  642.             $this->docparams = true;
  643.             $mqname = new QName($method$namespace);
  644.             $methodValue = new SOAP_Value($mqname->fqn()'Struct'$params,
  645.                                           array()$this->_options);
  646.             $soap_msg $this->makeEnvelope($methodValue,
  647.                                             $this->headersOut,
  648.                                             $this->_encoding,
  649.                                             $this->_options);
  650.         else {
  651.             if (!$params{
  652.                 $mqname = new QName($method$namespace);
  653.                 $params = new SOAP_Value($mqname->fqn()'Struct'null);
  654.             elseif ($this->_options['input'== 'parse'{
  655.                 if (is_array($params)) {
  656.                     $nparams = array();
  657.                     $keys array_keys($params);
  658.                     foreach ($keys as $k{
  659.                         if (gettype($params[$k]!= 'object'{
  660.                             $nparams[= new SOAP_Value($k,
  661.                                                         false,
  662.                                                         $params[$k]);
  663.                         else {
  664.                             $nparams[=$params[$k];
  665.                         }
  666.                     }
  667.                     $params =$nparams;
  668.                 }
  669.                 if ($this->_options['parameters']{
  670.                     $mqname = new QName($method$namespace);
  671.                     $params = new SOAP_Value($mqname->fqn(),
  672.                                              'Struct',
  673.                                              $params);
  674.                 }
  675.             }
  676.             $soap_msg $this->makeEnvelope($params,
  677.                                             $this->headersOut,
  678.                                             $this->_encoding,
  679.                                             $this->_options);
  680.         }
  681.         $this->headersOut = null;
  682.  
  683.         if (PEAR::isError($soap_msg)) {
  684.             return $this->_raiseSoapFault($soap_msg);
  685.         }
  686.  
  687.         // Handle MIME or DIME encoding.
  688.         // TODO: DIME encoding should move to the transport, do it here for
  689.         // now and for ease of getting it done.
  690.         if (count($this->_attachments)) {
  691.             if ((isset($this->_options['attachments']&&
  692.                  $this->_options['attachments'== 'Mime'||
  693.                 isset($this->_options['Mime'])) {
  694.                 $soap_msg $this->_makeMimeMessage($soap_msg$this->_encoding);
  695.             else {
  696.                 // default is dime
  697.                 $soap_msg $this->_makeDIMEMessage($soap_msg$this->_encoding);
  698.                 $this->_options['headers']['Content-Type''application/dime';
  699.             }
  700.             if (PEAR::isError($soap_msg)) {
  701.                 return $this->_raiseSoapFault($soap_msg);
  702.             }
  703.         }
  704.  
  705.         // Instantiate client.
  706.         if (is_array($soap_msg)) {
  707.             $soap_data $soap_msg['body'];
  708.             if (count($soap_msg['headers'])) {
  709.                 if (isset($this->_options['headers'])) {
  710.                     $this->_options['headers'array_merge($this->_options['headers']$soap_msg['headers']);
  711.                 else {
  712.                     $this->_options['headers'$soap_msg['headers'];
  713.                 }
  714.             }
  715.         else {
  716.             $soap_data $soap_msg;
  717.         }
  718.  
  719.         return $soap_data;
  720.     }
  721.  
  722.     /**
  723.      * Parses a SOAP response.
  724.      *
  725.      * @see SOAP_Parser::
  726.      *
  727.      * @param string $response    XML content of SOAP response.
  728.      * @param string $encoding    Character set encoding, defaults to 'UTF-8'.
  729.      * @param array $attachments  List of attachments.
  730.      */
  731.     function parseResponse($response$encoding$attachments)
  732.     {
  733.         // Parse the response.
  734.         $response = new SOAP_Parser($response$encoding$attachments);
  735.         if ($response->fault{
  736.             $fault $this->_raiseSoapFault($response->fault);
  737.             return $fault;
  738.         }
  739.  
  740.         // Return array of parameters.
  741.         $return $response->getResponse();
  742.         $headers $response->getHeaders();
  743.         if ($headers{
  744.             $this->headersIn = $this->_decodeResponse($headersfalse);
  745.         }
  746.  
  747.         $decoded $this->_decodeResponse($return);
  748.         return $decoded;
  749.     }
  750.  
  751.     /**
  752.      * Converts a complex SOAP_Value into a PHP Array
  753.      *
  754.      * @param SOAP_Value $response  Value object.
  755.      * @param boolean $shift 
  756.      *
  757.      * @return array 
  758.      */
  759.     function _decodeResponse($response$shift = true)
  760.     {
  761.         if (!$response{
  762.             $decoded = null;
  763.             return $decoded;
  764.         }
  765.  
  766.         // Check for valid response.
  767.         if (PEAR::isError($response)) {
  768.             $fault $this->_raiseSoapFault($response);
  769.             return $fault;
  770.         elseif (!is_a($response'soap_value')) {
  771.             $fault $this->_raiseSoapFault("Didn't get SOAP_Value object back from client");
  772.             return $fault;
  773.         }
  774.  
  775.         // Decode to native php datatype.
  776.         $returnArray $this->_decode($response);
  777.  
  778.         // Fault?
  779.         if (PEAR::isError($returnArray)) {
  780.             $fault $this->_raiseSoapFault($returnArray);
  781.             return $fault;
  782.         }
  783.  
  784.         if (is_object($returnArray&&
  785.             strcasecmp(get_class($returnArray)'stdClass'== 0{
  786.             $returnArray get_object_vars($returnArray);
  787.         }
  788.  
  789.         if (is_array($returnArray)) {
  790.             if (isset($returnArray['faultcode']||
  791.                 isset($returnArray[SOAP_BASE::SOAPENVPrefix().':faultcode'])) {
  792.                 $faultcode $faultstring $faultdetail $faultactor '';
  793.                 foreach ($returnArray as $k => $v{
  794.                     if (stristr($k'faultcode')) $faultcode $v;
  795.                     if (stristr($k'faultstring')) $faultstring $v;
  796.                     if (stristr($k'detail')) $faultdetail $v;
  797.                     if (stristr($k'faultactor')) $faultactor $v;
  798.                 }
  799.                 $fault $this->_raiseSoapFault($faultstring$faultdetail,
  800.                                                 $faultactor$faultcode);
  801.                 return $fault;
  802.             }
  803.             // Return array of return values.
  804.             if ($shift && count($returnArray== 1{
  805.                 $decoded array_shift($returnArray);
  806.                 return $decoded;
  807.             }
  808.             return $returnArray;
  809.         }
  810.  
  811.         return $returnArray;
  812.     }
  813.  
  814.     /**
  815.      * Returns the outgoing and incoming traffic on the transport level.
  816.      *
  817.      * Tracing has to be enabled.
  818.      *
  819.      * @see setTrace()
  820.      *
  821.      * @return string  The complete traffic between the client and the server.
  822.      */
  823.     function getWire()
  824.     {
  825.         if ($this->_options['trace'&&
  826.             ($this->_last_request || $this->_last_response)) {
  827.             return "OUTGOING:\n\n" .
  828.                 $this->_last_request .
  829.                 "\n\nINCOMING\n\n" .
  830.                 preg_replace("/></",">\r\n<"$this->_last_response);
  831.         }
  832.  
  833.         return null;
  834.     }
  835.  
  836. }

Documentation generated on Mon, 04 Aug 2008 20:00:14 -0400 by phpDocumentor 1.4.0. PEAR Logo Copyright © PHP Group 2004.