PageRenderTime 52ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/Zend/Soap/Server.php

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