web/lib/Zend/Soap/Server.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_Soap
       
    17  * @subpackage Server
       
    18  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    19  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    20  */
       
    21 
       
    22 /**
       
    23  * @see Zend_Server_Interface
       
    24  */
       
    25 require_once 'Zend/Server/Interface.php';
       
    26 
       
    27 /**
       
    28  * Zend_Soap_Server
       
    29  *
       
    30  * @category   Zend
       
    31  * @package    Zend_Soap
       
    32  * @subpackage Server
       
    33  * @uses       Zend_Server_Interface
       
    34  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    35  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    36  * @version    $Id: Server.php 22223 2010-05-21 08:06:47Z jan $
       
    37  */
       
    38 class Zend_Soap_Server implements Zend_Server_Interface
       
    39 {
       
    40     /**
       
    41      * Actor URI
       
    42      * @var string URI
       
    43      */
       
    44     protected $_actor;
       
    45 
       
    46     /**
       
    47      * Class registered with this server
       
    48      * @var string
       
    49      */
       
    50     protected $_class;
       
    51 
       
    52     /**
       
    53      * Arguments to pass to {@link $_class} constructor
       
    54      * @var array
       
    55      */
       
    56     protected $_classArgs = array();
       
    57 
       
    58     /**
       
    59      * Object registered with this server
       
    60      */
       
    61     protected $_object;
       
    62 
       
    63     /**
       
    64      * Array of SOAP type => PHP class pairings for handling return/incoming values
       
    65      * @var array
       
    66      */
       
    67     protected $_classmap;
       
    68 
       
    69     /**
       
    70      * Encoding
       
    71      * @var string
       
    72      */
       
    73     protected $_encoding;
       
    74 
       
    75     /**
       
    76      * SOAP Server Features
       
    77      *
       
    78      * @var int
       
    79      */
       
    80     protected $_features;
       
    81 
       
    82     /**
       
    83      * WSDL Caching Options of SOAP Server
       
    84      *
       
    85      * @var mixed
       
    86      */
       
    87     protected $_wsdlCache;
       
    88 
       
    89 
       
    90     /**
       
    91      * Registered fault exceptions
       
    92      * @var array
       
    93      */
       
    94     protected $_faultExceptions = array();
       
    95 
       
    96     /**
       
    97      * Functions registered with this server; may be either an array or the SOAP_FUNCTIONS_ALL
       
    98      * constant
       
    99      * @var array|int
       
   100      */
       
   101     protected $_functions = array();
       
   102 
       
   103     /**
       
   104      * Persistence mode; should be one of the SOAP persistence constants
       
   105      * @var int
       
   106      */
       
   107     protected $_persistence;
       
   108 
       
   109     /**
       
   110      * Request XML
       
   111      * @var string
       
   112      */
       
   113     protected $_request;
       
   114 
       
   115     /**
       
   116      * Response XML
       
   117      * @var string
       
   118      */
       
   119     protected $_response;
       
   120 
       
   121     /**
       
   122      * Flag: whether or not {@link handle()} should return a response instead
       
   123      * of automatically emitting it.
       
   124      * @var boolean
       
   125      */
       
   126     protected $_returnResponse = false;
       
   127 
       
   128     /**
       
   129      * SOAP version to use; SOAP_1_2 by default, to allow processing of headers
       
   130      * @var int
       
   131      */
       
   132     protected $_soapVersion = SOAP_1_2;
       
   133 
       
   134     /**
       
   135      * URI or path to WSDL
       
   136      * @var string
       
   137      */
       
   138     protected $_wsdl;
       
   139 
       
   140     /**
       
   141      * URI namespace for SOAP server
       
   142      * @var string URI
       
   143      */
       
   144     protected $_uri;
       
   145 
       
   146     /**
       
   147      * Constructor
       
   148      *
       
   149      * Sets display_errors INI setting to off (prevent client errors due to bad
       
   150      * XML in response). Registers {@link handlePhpErrors()} as error handler
       
   151      * for E_USER_ERROR.
       
   152      *
       
   153      * If $wsdl is provided, it is passed on to {@link setWsdl()}; if any
       
   154      * options are specified, they are passed on to {@link setOptions()}.
       
   155      *
       
   156      * @param string $wsdl
       
   157      * @param array $options
       
   158      * @return void
       
   159      */
       
   160     public function __construct($wsdl = null, array $options = null)
       
   161     {
       
   162         if (!extension_loaded('soap')) {
       
   163             require_once 'Zend/Soap/Server/Exception.php';
       
   164             throw new Zend_Soap_Server_Exception('SOAP extension is not loaded.');
       
   165         }
       
   166 
       
   167         if (null !== $wsdl) {
       
   168             $this->setWsdl($wsdl);
       
   169         }
       
   170 
       
   171         if (null !== $options) {
       
   172             $this->setOptions($options);
       
   173         }
       
   174     }
       
   175 
       
   176     /**
       
   177      * Set Options
       
   178      *
       
   179      * Allows setting options as an associative array of option => value pairs.
       
   180      *
       
   181      * @param  array|Zend_Config $options
       
   182      * @return Zend_Soap_Server
       
   183      */
       
   184     public function setOptions($options)
       
   185     {
       
   186         if($options instanceof Zend_Config) {
       
   187             $options = $options->toArray();
       
   188         }
       
   189 
       
   190         foreach ($options as $key => $value) {
       
   191             switch ($key) {
       
   192                 case 'actor':
       
   193                     $this->setActor($value);
       
   194                     break;
       
   195                 case 'classmap':
       
   196                 case 'classMap':
       
   197                     $this->setClassmap($value);
       
   198                     break;
       
   199                 case 'encoding':
       
   200                     $this->setEncoding($value);
       
   201                     break;
       
   202                 case 'soapVersion':
       
   203                 case 'soap_version':
       
   204                     $this->setSoapVersion($value);
       
   205                     break;
       
   206                 case 'uri':
       
   207                     $this->setUri($value);
       
   208                     break;
       
   209                 case 'wsdl':
       
   210                     $this->setWsdl($value);
       
   211                     break;
       
   212                 case 'featues':
       
   213                     trigger_error(__METHOD__ . ': the option "featues" is deprecated as of 1.10.x and will be removed with 2.0.0; use "features" instead', E_USER_NOTICE);
       
   214                 case 'features':
       
   215                     $this->setSoapFeatures($value);
       
   216                     break;
       
   217                 case 'cache_wsdl':
       
   218                     $this->setWsdlCache($value);
       
   219                     break;
       
   220                 default:
       
   221                     break;
       
   222             }
       
   223         }
       
   224 
       
   225         return $this;
       
   226     }
       
   227 
       
   228     /**
       
   229      * Return array of options suitable for using with SoapServer constructor
       
   230      *
       
   231      * @return array
       
   232      */
       
   233     public function getOptions()
       
   234     {
       
   235         $options = array();
       
   236         if (null !== $this->_actor) {
       
   237             $options['actor'] = $this->_actor;
       
   238         }
       
   239 
       
   240         if (null !== $this->_classmap) {
       
   241             $options['classmap'] = $this->_classmap;
       
   242         }
       
   243 
       
   244         if (null !== $this->_encoding) {
       
   245             $options['encoding'] = $this->_encoding;
       
   246         }
       
   247 
       
   248         if (null !== $this->_soapVersion) {
       
   249             $options['soap_version'] = $this->_soapVersion;
       
   250         }
       
   251 
       
   252         if (null !== $this->_uri) {
       
   253             $options['uri'] = $this->_uri;
       
   254         }
       
   255 
       
   256         if(null !== $this->_features) {
       
   257             $options['features'] = $this->_features;
       
   258         }
       
   259 
       
   260         if(null !== $this->_wsdlCache) {
       
   261             $options['cache_wsdl'] = $this->_wsdlCache;
       
   262         }
       
   263 
       
   264         return $options;
       
   265     }
       
   266 
       
   267     /**
       
   268      * Set encoding
       
   269      *
       
   270      * @param  string $encoding
       
   271      * @return Zend_Soap_Server
       
   272      * @throws Zend_Soap_Server_Exception with invalid encoding argument
       
   273      */
       
   274     public function setEncoding($encoding)
       
   275     {
       
   276         if (!is_string($encoding)) {
       
   277             require_once 'Zend/Soap/Server/Exception.php';
       
   278             throw new Zend_Soap_Server_Exception('Invalid encoding specified');
       
   279         }
       
   280 
       
   281         $this->_encoding = $encoding;
       
   282         return $this;
       
   283     }
       
   284 
       
   285     /**
       
   286      * Get encoding
       
   287      *
       
   288      * @return string
       
   289      */
       
   290     public function getEncoding()
       
   291     {
       
   292         return $this->_encoding;
       
   293     }
       
   294 
       
   295     /**
       
   296      * Set SOAP version
       
   297      *
       
   298      * @param  int $version One of the SOAP_1_1 or SOAP_1_2 constants
       
   299      * @return Zend_Soap_Server
       
   300      * @throws Zend_Soap_Server_Exception with invalid soap version argument
       
   301      */
       
   302     public function setSoapVersion($version)
       
   303     {
       
   304         if (!in_array($version, array(SOAP_1_1, SOAP_1_2))) {
       
   305             require_once 'Zend/Soap/Server/Exception.php';
       
   306             throw new Zend_Soap_Server_Exception('Invalid soap version specified');
       
   307         }
       
   308 
       
   309         $this->_soapVersion = $version;
       
   310         return $this;
       
   311     }
       
   312 
       
   313     /**
       
   314      * Get SOAP version
       
   315      *
       
   316      * @return int
       
   317      */
       
   318     public function getSoapVersion()
       
   319     {
       
   320         return $this->_soapVersion;
       
   321     }
       
   322 
       
   323     /**
       
   324      * Check for valid URN
       
   325      *
       
   326      * @param  string $urn
       
   327      * @return true
       
   328      * @throws Zend_Soap_Server_Exception on invalid URN
       
   329      */
       
   330     public function validateUrn($urn)
       
   331     {
       
   332         $scheme = parse_url($urn, PHP_URL_SCHEME);
       
   333         if ($scheme === false || $scheme === null) {
       
   334             require_once 'Zend/Soap/Server/Exception.php';
       
   335             throw new Zend_Soap_Server_Exception('Invalid URN');
       
   336         }
       
   337 
       
   338         return true;
       
   339     }
       
   340 
       
   341     /**
       
   342      * Set actor
       
   343      *
       
   344      * Actor is the actor URI for the server.
       
   345      *
       
   346      * @param  string $actor
       
   347      * @return Zend_Soap_Server
       
   348      */
       
   349     public function setActor($actor)
       
   350     {
       
   351         $this->validateUrn($actor);
       
   352         $this->_actor = $actor;
       
   353         return $this;
       
   354     }
       
   355 
       
   356     /**
       
   357      * Retrieve actor
       
   358      *
       
   359      * @return string
       
   360      */
       
   361     public function getActor()
       
   362     {
       
   363         return $this->_actor;
       
   364     }
       
   365 
       
   366     /**
       
   367      * Set URI
       
   368      *
       
   369      * URI in SoapServer is actually the target namespace, not a URI; $uri must begin with 'urn:'.
       
   370      *
       
   371      * @param  string $uri
       
   372      * @return Zend_Soap_Server
       
   373      * @throws Zend_Soap_Server_Exception with invalid uri argument
       
   374      */
       
   375     public function setUri($uri)
       
   376     {
       
   377         $this->validateUrn($uri);
       
   378         $this->_uri = $uri;
       
   379         return $this;
       
   380     }
       
   381 
       
   382     /**
       
   383      * Retrieve URI
       
   384      *
       
   385      * @return string
       
   386      */
       
   387     public function getUri()
       
   388     {
       
   389         return $this->_uri;
       
   390     }
       
   391 
       
   392     /**
       
   393      * Set classmap
       
   394      *
       
   395      * @param  array $classmap
       
   396      * @return Zend_Soap_Server
       
   397      * @throws Zend_Soap_Server_Exception for any invalid class in the class map
       
   398      */
       
   399     public function setClassmap($classmap)
       
   400     {
       
   401         if (!is_array($classmap)) {
       
   402             /**
       
   403              * @see Zend_Soap_Server_Exception
       
   404              */
       
   405             require_once 'Zend/Soap/Server/Exception.php';
       
   406             throw new Zend_Soap_Server_Exception('Classmap must be an array');
       
   407         }
       
   408         foreach ($classmap as $type => $class) {
       
   409             if (!class_exists($class)) {
       
   410                 /**
       
   411                  * @see Zend_Soap_Server_Exception
       
   412                  */
       
   413                 require_once 'Zend/Soap/Server/Exception.php';
       
   414                 throw new Zend_Soap_Server_Exception('Invalid class in class map');
       
   415             }
       
   416         }
       
   417 
       
   418         $this->_classmap = $classmap;
       
   419         return $this;
       
   420     }
       
   421 
       
   422     /**
       
   423      * Retrieve classmap
       
   424      *
       
   425      * @return mixed
       
   426      */
       
   427     public function getClassmap()
       
   428     {
       
   429         return $this->_classmap;
       
   430     }
       
   431 
       
   432     /**
       
   433      * Set wsdl
       
   434      *
       
   435      * @param string $wsdl  URI or path to a WSDL
       
   436      * @return Zend_Soap_Server
       
   437      */
       
   438     public function setWsdl($wsdl)
       
   439     {
       
   440         $this->_wsdl = $wsdl;
       
   441         return $this;
       
   442     }
       
   443 
       
   444     /**
       
   445      * Retrieve wsdl
       
   446      *
       
   447      * @return string
       
   448      */
       
   449     public function getWsdl()
       
   450     {
       
   451         return $this->_wsdl;
       
   452     }
       
   453 
       
   454     /**
       
   455      * Set the SOAP Feature options.
       
   456      *
       
   457      * @param  string|int $feature
       
   458      * @return Zend_Soap_Server
       
   459      */
       
   460     public function setSoapFeatures($feature)
       
   461     {
       
   462         $this->_features = $feature;
       
   463         return $this;
       
   464     }
       
   465 
       
   466     /**
       
   467      * Return current SOAP Features options
       
   468      *
       
   469      * @return int
       
   470      */
       
   471     public function getSoapFeatures()
       
   472     {
       
   473         return $this->_features;
       
   474     }
       
   475 
       
   476     /**
       
   477      * Set the SOAP Wsdl Caching Options
       
   478      *
       
   479      * @param string|int|boolean $caching
       
   480      * @return Zend_Soap_Server
       
   481      */
       
   482     public function setWsdlCache($options)
       
   483     {
       
   484         $this->_wsdlCache = $options;
       
   485         return $this;
       
   486     }
       
   487 
       
   488     /**
       
   489      * Get current SOAP Wsdl Caching option
       
   490      */
       
   491     public function getWsdlCache()
       
   492     {
       
   493         return $this->_wsdlCache;
       
   494     }
       
   495 
       
   496     /**
       
   497      * Attach a function as a server method
       
   498      *
       
   499      * @param array|string $function Function name, array of function names to attach,
       
   500      * or SOAP_FUNCTIONS_ALL to attach all functions
       
   501      * @param  string $namespace Ignored
       
   502      * @return Zend_Soap_Server
       
   503      * @throws Zend_Soap_Server_Exception on invalid functions
       
   504      */
       
   505     public function addFunction($function, $namespace = '')
       
   506     {
       
   507         // Bail early if set to SOAP_FUNCTIONS_ALL
       
   508         if ($this->_functions == SOAP_FUNCTIONS_ALL) {
       
   509             return $this;
       
   510         }
       
   511 
       
   512         if (is_array($function)) {
       
   513             foreach ($function as $func) {
       
   514                 if (is_string($func) && function_exists($func)) {
       
   515                     $this->_functions[] = $func;
       
   516                 } else {
       
   517                     require_once 'Zend/Soap/Server/Exception.php';
       
   518                     throw new Zend_Soap_Server_Exception('One or more invalid functions specified in array');
       
   519                 }
       
   520             }
       
   521             $this->_functions = array_merge($this->_functions, $function);
       
   522         } elseif (is_string($function) && function_exists($function)) {
       
   523             $this->_functions[] = $function;
       
   524         } elseif ($function == SOAP_FUNCTIONS_ALL) {
       
   525             $this->_functions = SOAP_FUNCTIONS_ALL;
       
   526         } else {
       
   527             require_once 'Zend/Soap/Server/Exception.php';
       
   528             throw new Zend_Soap_Server_Exception('Invalid function specified');
       
   529         }
       
   530 
       
   531         if (is_array($this->_functions)) {
       
   532             $this->_functions = array_unique($this->_functions);
       
   533         }
       
   534 
       
   535         return $this;
       
   536     }
       
   537 
       
   538     /**
       
   539      * Attach a class to a server
       
   540      *
       
   541      * Accepts a class name to use when handling requests. Any additional
       
   542      * arguments will be passed to that class' constructor when instantiated.
       
   543      *
       
   544      * See {@link setObject()} to set preconfigured object instances as request handlers.
       
   545      *
       
   546      * @param string $class Class Name which executes SOAP Requests at endpoint.
       
   547      * @return Zend_Soap_Server
       
   548      * @throws Zend_Soap_Server_Exception if called more than once, or if class
       
   549      * does not exist
       
   550      */
       
   551     public function setClass($class, $namespace = '', $argv = null)
       
   552     {
       
   553         if (isset($this->_class)) {
       
   554             require_once 'Zend/Soap/Server/Exception.php';
       
   555             throw new Zend_Soap_Server_Exception('A class has already been registered with this soap server instance');
       
   556         }
       
   557 
       
   558         if (!is_string($class)) {
       
   559             require_once 'Zend/Soap/Server/Exception.php';
       
   560             throw new Zend_Soap_Server_Exception('Invalid class argument (' . gettype($class) . ')');
       
   561         }
       
   562 
       
   563         if (!class_exists($class)) {
       
   564             require_once 'Zend/Soap/Server/Exception.php';
       
   565             throw new Zend_Soap_Server_Exception('Class "' . $class . '" does not exist');
       
   566         }
       
   567 
       
   568         $this->_class = $class;
       
   569         if (1 < func_num_args()) {
       
   570             $argv = func_get_args();
       
   571             array_shift($argv);
       
   572             $this->_classArgs = $argv;
       
   573         }
       
   574 
       
   575         return $this;
       
   576     }
       
   577 
       
   578     /**
       
   579      * Attach an object to a server
       
   580      *
       
   581      * Accepts an instanciated object to use when handling requests.
       
   582      *
       
   583      * @param object $object
       
   584      * @return Zend_Soap_Server
       
   585      */
       
   586     public function setObject($object)
       
   587     {
       
   588         if(!is_object($object)) {
       
   589             require_once 'Zend/Soap/Server/Exception.php';
       
   590             throw new Zend_Soap_Server_Exception('Invalid object argument ('.gettype($object).')');
       
   591         }
       
   592 
       
   593         if(isset($this->_object)) {
       
   594             require_once 'Zend/Soap/Server/Exception.php';
       
   595             throw new Zend_Soap_Server_Exception('An object has already been registered with this soap server instance');
       
   596         }
       
   597 
       
   598         $this->_object = $object;
       
   599 
       
   600         return $this;
       
   601     }
       
   602 
       
   603     /**
       
   604      * Return a server definition array
       
   605      *
       
   606      * Returns a list of all functions registered with {@link addFunction()},
       
   607      * merged with all public methods of the class set with {@link setClass()}
       
   608      * (if any).
       
   609      *
       
   610      * @access public
       
   611      * @return array
       
   612      */
       
   613     public function getFunctions()
       
   614     {
       
   615         $functions = array();
       
   616         if (null !== $this->_class) {
       
   617             $functions = get_class_methods($this->_class);
       
   618         } elseif (null !== $this->_object) {
       
   619             $functions = get_class_methods($this->_object);
       
   620         }
       
   621 
       
   622         return array_merge((array) $this->_functions, $functions);
       
   623     }
       
   624 
       
   625     /**
       
   626      * Unimplemented: Load server definition
       
   627      *
       
   628      * @param array $array
       
   629      * @return void
       
   630      * @throws Zend_Soap_Server_Exception Unimplemented
       
   631      */
       
   632     public function loadFunctions($definition)
       
   633     {
       
   634         require_once 'Zend/Soap/Server/Exception.php';
       
   635         throw new Zend_Soap_Server_Exception('Unimplemented');
       
   636     }
       
   637 
       
   638     /**
       
   639      * Set server persistence
       
   640      *
       
   641      * @param int $mode
       
   642      * @return Zend_Soap_Server
       
   643      */
       
   644     public function setPersistence($mode)
       
   645     {
       
   646         if (!in_array($mode, array(SOAP_PERSISTENCE_SESSION, SOAP_PERSISTENCE_REQUEST))) {
       
   647             require_once 'Zend/Soap/Server/Exception.php';
       
   648             throw new Zend_Soap_Server_Exception('Invalid persistence mode specified');
       
   649         }
       
   650 
       
   651         $this->_persistence = $mode;
       
   652         return $this;
       
   653     }
       
   654 
       
   655     /**
       
   656      * Get server persistence
       
   657      *
       
   658      * @return Zend_Soap_Server
       
   659      */
       
   660     public function getPersistence()
       
   661     {
       
   662         return $this->_persistence;
       
   663     }
       
   664 
       
   665     /**
       
   666      * Set request
       
   667      *
       
   668      * $request may be any of:
       
   669      * - DOMDocument; if so, then cast to XML
       
   670      * - DOMNode; if so, then grab owner document and cast to XML
       
   671      * - SimpleXMLElement; if so, then cast to XML
       
   672      * - stdClass; if so, calls __toString() and verifies XML
       
   673      * - string; if so, verifies XML
       
   674      *
       
   675      * @param DOMDocument|DOMNode|SimpleXMLElement|stdClass|string $request
       
   676      * @return Zend_Soap_Server
       
   677      */
       
   678     protected function _setRequest($request)
       
   679     {
       
   680         if ($request instanceof DOMDocument) {
       
   681             $xml = $request->saveXML();
       
   682         } elseif ($request instanceof DOMNode) {
       
   683             $xml = $request->ownerDocument->saveXML();
       
   684         } elseif ($request instanceof SimpleXMLElement) {
       
   685             $xml = $request->asXML();
       
   686         } elseif (is_object($request) || is_string($request)) {
       
   687             if (is_object($request)) {
       
   688                 $xml = $request->__toString();
       
   689             } else {
       
   690                 $xml = $request;
       
   691             }
       
   692 
       
   693             $dom = new DOMDocument();
       
   694             if(strlen($xml) == 0 || !$dom->loadXML($xml)) {
       
   695                 require_once 'Zend/Soap/Server/Exception.php';
       
   696                 throw new Zend_Soap_Server_Exception('Invalid XML');
       
   697             }
       
   698         }
       
   699         $this->_request = $xml;
       
   700         return $this;
       
   701     }
       
   702 
       
   703     /**
       
   704      * Retrieve request XML
       
   705      *
       
   706      * @return string
       
   707      */
       
   708     public function getLastRequest()
       
   709     {
       
   710         return $this->_request;
       
   711     }
       
   712 
       
   713     /**
       
   714      * Set return response flag
       
   715      *
       
   716      * If true, {@link handle()} will return the response instead of
       
   717      * automatically sending it back to the requesting client.
       
   718      *
       
   719      * The response is always available via {@link getResponse()}.
       
   720      *
       
   721      * @param boolean $flag
       
   722      * @return Zend_Soap_Server
       
   723      */
       
   724     public function setReturnResponse($flag)
       
   725     {
       
   726         $this->_returnResponse = ($flag) ? true : false;
       
   727         return $this;
       
   728     }
       
   729 
       
   730     /**
       
   731      * Retrieve return response flag
       
   732      *
       
   733      * @return boolean
       
   734      */
       
   735     public function getReturnResponse()
       
   736     {
       
   737         return $this->_returnResponse;
       
   738     }
       
   739 
       
   740     /**
       
   741      * Get response XML
       
   742      *
       
   743      * @return string
       
   744      */
       
   745     public function getLastResponse()
       
   746     {
       
   747         return $this->_response;
       
   748     }
       
   749 
       
   750     /**
       
   751      * Get SoapServer object
       
   752      *
       
   753      * Uses {@link $_wsdl} and return value of {@link getOptions()} to instantiate
       
   754      * SoapServer object, and then registers any functions or class with it, as
       
   755      * well as peristence.
       
   756      *
       
   757      * @return SoapServer
       
   758      */
       
   759     protected function _getSoap()
       
   760     {
       
   761         $options = $this->getOptions();
       
   762         $server  = new SoapServer($this->_wsdl, $options);
       
   763 
       
   764         if (!empty($this->_functions)) {
       
   765             $server->addFunction($this->_functions);
       
   766         }
       
   767 
       
   768         if (!empty($this->_class)) {
       
   769             $args = $this->_classArgs;
       
   770             array_unshift($args, $this->_class);
       
   771             call_user_func_array(array($server, 'setClass'), $args);
       
   772         }
       
   773 
       
   774         if (!empty($this->_object)) {
       
   775             $server->setObject($this->_object);
       
   776         }
       
   777 
       
   778         if (null !== $this->_persistence) {
       
   779             $server->setPersistence($this->_persistence);
       
   780         }
       
   781 
       
   782         return $server;
       
   783     }
       
   784 
       
   785     /**
       
   786      * Handle a request
       
   787      *
       
   788      * Instantiates SoapServer object with options set in object, and
       
   789      * dispatches its handle() method.
       
   790      *
       
   791      * $request may be any of:
       
   792      * - DOMDocument; if so, then cast to XML
       
   793      * - DOMNode; if so, then grab owner document and cast to XML
       
   794      * - SimpleXMLElement; if so, then cast to XML
       
   795      * - stdClass; if so, calls __toString() and verifies XML
       
   796      * - string; if so, verifies XML
       
   797      *
       
   798      * If no request is passed, pulls request using php:://input (for
       
   799      * cross-platform compatability purposes).
       
   800      *
       
   801      * @param DOMDocument|DOMNode|SimpleXMLElement|stdClass|string $request Optional request
       
   802      * @return void|string
       
   803      */
       
   804     public function handle($request = null)
       
   805     {
       
   806         if (null === $request) {
       
   807             $request = file_get_contents('php://input');
       
   808         }
       
   809 
       
   810         // Set Zend_Soap_Server error handler
       
   811         $displayErrorsOriginalState = $this->_initializeSoapErrorContext();
       
   812 
       
   813         $setRequestException = null;
       
   814         /**
       
   815          * @see Zend_Soap_Server_Exception
       
   816          */
       
   817         require_once 'Zend/Soap/Server/Exception.php';
       
   818         try {
       
   819             $this->_setRequest($request);
       
   820         } catch (Zend_Soap_Server_Exception $e) {
       
   821             $setRequestException = $e;
       
   822         }
       
   823 
       
   824         $soap = $this->_getSoap();
       
   825 
       
   826         ob_start();
       
   827         if($setRequestException instanceof Exception) {
       
   828             // Send SOAP fault message if we've catched exception
       
   829             $soap->fault("Sender", $setRequestException->getMessage());
       
   830         } else {
       
   831             try {
       
   832                 $soap->handle($request);
       
   833             } catch (Exception $e) {
       
   834                 $fault = $this->fault($e);
       
   835                 $soap->fault($fault->faultcode, $fault->faultstring);
       
   836             }
       
   837         }
       
   838         $this->_response = ob_get_clean();
       
   839 
       
   840         // Restore original error handler
       
   841         restore_error_handler();
       
   842         ini_set('display_errors', $displayErrorsOriginalState);
       
   843 
       
   844         if (!$this->_returnResponse) {
       
   845             echo $this->_response;
       
   846             return;
       
   847         }
       
   848 
       
   849         return $this->_response;
       
   850     }
       
   851 
       
   852     /**
       
   853      * Method initalizes the error context that the SOAPServer enviroment will run in.
       
   854      *
       
   855      * @return boolean display_errors original value
       
   856      */
       
   857     protected function _initializeSoapErrorContext()
       
   858     {
       
   859         $displayErrorsOriginalState = ini_get('display_errors');
       
   860         ini_set('display_errors', false);
       
   861         set_error_handler(array($this, 'handlePhpErrors'), E_USER_ERROR);
       
   862         return $displayErrorsOriginalState;
       
   863     }
       
   864 
       
   865     /**
       
   866      * Register a valid fault exception
       
   867      *
       
   868      * @param  string|array $class Exception class or array of exception classes
       
   869      * @return Zend_Soap_Server
       
   870      */
       
   871     public function registerFaultException($class)
       
   872     {
       
   873         $this->_faultExceptions = array_merge($this->_faultExceptions, (array) $class);
       
   874         return $this;
       
   875     }
       
   876 
       
   877     /**
       
   878      * Deregister a fault exception from the fault exception stack
       
   879      *
       
   880      * @param  string $class
       
   881      * @return boolean
       
   882      */
       
   883     public function deregisterFaultException($class)
       
   884     {
       
   885         if (in_array($class, $this->_faultExceptions, true)) {
       
   886             $index = array_search($class, $this->_faultExceptions);
       
   887             unset($this->_faultExceptions[$index]);
       
   888             return true;
       
   889         }
       
   890 
       
   891         return false;
       
   892     }
       
   893 
       
   894     /**
       
   895      * Return fault exceptions list
       
   896      *
       
   897      * @return array
       
   898      */
       
   899     public function getFaultExceptions()
       
   900     {
       
   901         return $this->_faultExceptions;
       
   902     }
       
   903 
       
   904     /**
       
   905      * Generate a server fault
       
   906      *
       
   907      * Note that the arguments are reverse to those of SoapFault.
       
   908      *
       
   909      * If an exception is passed as the first argument, its message and code
       
   910      * will be used to create the fault object if it has been registered via
       
   911      * {@Link registerFaultException()}.
       
   912      *
       
   913      * @link   http://www.w3.org/TR/soap12-part1/#faultcodes
       
   914      * @param  string|Exception $fault
       
   915      * @param  string $code SOAP Fault Codes
       
   916      * @return SoapFault
       
   917      */
       
   918     public function fault($fault = null, $code = "Receiver")
       
   919     {
       
   920         if ($fault instanceof Exception) {
       
   921             $class = get_class($fault);
       
   922             if (in_array($class, $this->_faultExceptions)) {
       
   923                 $message = $fault->getMessage();
       
   924                 $eCode   = $fault->getCode();
       
   925                 $code    = empty($eCode) ? $code : $eCode;
       
   926             } else {
       
   927                 $message = 'Unknown error';
       
   928             }
       
   929         } elseif(is_string($fault)) {
       
   930             $message = $fault;
       
   931         } else {
       
   932             $message = 'Unknown error';
       
   933         }
       
   934 
       
   935         $allowedFaultModes = array(
       
   936             'VersionMismatch', 'MustUnderstand', 'DataEncodingUnknown',
       
   937             'Sender', 'Receiver', 'Server'
       
   938         );
       
   939         if(!in_array($code, $allowedFaultModes)) {
       
   940             $code = "Receiver";
       
   941         }
       
   942 
       
   943         return new SoapFault($code, $message);
       
   944     }
       
   945 
       
   946     /**
       
   947      * Throw PHP errors as SoapFaults
       
   948      *
       
   949      * @param int $errno
       
   950      * @param string $errstr
       
   951      * @param string $errfile
       
   952      * @param int $errline
       
   953      * @param array $errcontext
       
   954      * @return void
       
   955      * @throws SoapFault
       
   956      */
       
   957     public function handlePhpErrors($errno, $errstr, $errfile = null, $errline = null, array $errcontext = null)
       
   958     {
       
   959         throw $this->fault($errstr, "Receiver");
       
   960     }
       
   961 }