PageRenderTime 61ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/framework/web/services/CWebService.php

https://bitbucket.org/diegoaraujo/alexikeda
PHP | 283 lines | 146 code | 18 blank | 119 comment | 25 complexity | e9a3639e0b384b39081a0979f7570832 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, BSD-2-Clause
  1. <?php
  2. /**
  3. * CWebService class file.
  4. *
  5. * @author Qiang Xue <qiang.xue@gmail.com>
  6. * @link http://www.yiiframework.com/
  7. * @copyright Copyright &copy; 2008-2011 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. /**
  11. * CWebService encapsulates SoapServer and provides a WSDL-based web service.
  12. *
  13. * PHP SOAP extension is required.
  14. *
  15. * CWebService makes use of {@link CWsdlGenerator} and can generate the WSDL
  16. * on-the-fly without requiring you to write complex WSDL.
  17. *
  18. * To generate the WSDL based on doc comment blocks in the service provider class,
  19. * call {@link generateWsdl} or {@link renderWsdl}. To process the web service
  20. * requests, call {@link run}.
  21. *
  22. * @author Qiang Xue <qiang.xue@gmail.com>
  23. * @version $Id: CWebService.php 3277 2011-06-15 15:27:52Z qiang.xue $
  24. * @package system.web.services
  25. * @since 1.0
  26. */
  27. class CWebService extends CComponent
  28. {
  29. const SOAP_ERROR=1001;
  30. /**
  31. * @var string|object the web service provider class or object.
  32. * If specified as a class name, it can be a path alias.
  33. */
  34. public $provider;
  35. /**
  36. * @var string the URL for WSDL. This is required by {@link run()}.
  37. */
  38. public $wsdlUrl;
  39. /**
  40. * @var string the URL for the Web service. This is required by {@link generateWsdl()} and {@link renderWsdl()}.
  41. */
  42. public $serviceUrl;
  43. /**
  44. * @var integer number of seconds that the generated WSDL can remain valid in cache. Defaults to 0, meaning no caching.
  45. */
  46. public $wsdlCacheDuration=0;
  47. /**
  48. * @var string the ID of the cache application component that is used to cache the generated WSDL.
  49. * Defaults to 'cache' which refers to the primary cache application component.
  50. * Set this property to false if you want to disable caching WSDL.
  51. * @since 1.0.10
  52. */
  53. public $cacheID='cache';
  54. /**
  55. * @var string encoding of the Web service. Defaults to 'UTF-8'.
  56. */
  57. public $encoding='UTF-8';
  58. /**
  59. * @var array a list of classes that are declared as complex types in WSDL.
  60. * This should be an array with WSDL types as keys and names of PHP classes as values.
  61. * A PHP class can also be specified as a path alias.
  62. * @see http://www.php.net/manual/en/function.soap-soapserver-construct.php
  63. */
  64. public $classMap=array();
  65. /**
  66. * @var string actor of the SOAP service. Defaults to null, meaning not set.
  67. */
  68. public $actor;
  69. /**
  70. * @var string SOAP version (e.g. '1.1' or '1.2'). Defaults to null, meaning not set.
  71. */
  72. public $soapVersion;
  73. /**
  74. * @var integer the persistence mode of the SOAP server.
  75. * @see http://www.php.net/manual/en/function.soap-soapserver-setpersistence.php
  76. */
  77. public $persistence;
  78. private $_method;
  79. /**
  80. * Constructor.
  81. * @param mixed $provider the web service provider class name or object
  82. * @param string $wsdlUrl the URL for WSDL. This is required by {@link run()}.
  83. * @param string $serviceUrl the URL for the Web service. This is required by {@link generateWsdl()} and {@link renderWsdl()}.
  84. */
  85. public function __construct($provider,$wsdlUrl,$serviceUrl)
  86. {
  87. $this->provider=$provider;
  88. $this->wsdlUrl=$wsdlUrl;
  89. $this->serviceUrl=$serviceUrl;
  90. }
  91. /**
  92. * The PHP error handler.
  93. * @param CErrorEvent $event the PHP error event
  94. */
  95. public function handleError($event)
  96. {
  97. $event->handled=true;
  98. $message=$event->message;
  99. if(YII_DEBUG)
  100. {
  101. $trace=debug_backtrace();
  102. if(isset($trace[2]) && isset($trace[2]['file']) && isset($trace[2]['line']))
  103. $message.=' ('.$trace[2]['file'].':'.$trace[2]['line'].')';
  104. }
  105. throw new CException($message,self::SOAP_ERROR);
  106. }
  107. /**
  108. * Generates and displays the WSDL as defined by the provider.
  109. * @see generateWsdl
  110. */
  111. public function renderWsdl()
  112. {
  113. $wsdl=$this->generateWsdl();
  114. header('Content-Type: text/xml;charset='.$this->encoding);
  115. header('Content-Length: '.(function_exists('mb_strlen') ? mb_strlen($wsdl,'8bit') : strlen($wsdl)));
  116. echo $wsdl;
  117. }
  118. /**
  119. * Generates the WSDL as defined by the provider.
  120. * The cached version may be used if the WSDL is found valid in cache.
  121. * @return string the generated WSDL
  122. * @see wsdlCacheDuration
  123. */
  124. public function generateWsdl()
  125. {
  126. $providerClass=is_object($this->provider) ? get_class($this->provider) : Yii::import($this->provider,true);
  127. if($this->wsdlCacheDuration>0 && $this->cacheID!==false && ($cache=Yii::app()->getComponent($this->cacheID))!==null)
  128. {
  129. $key='Yii.CWebService.'.$providerClass.$this->serviceUrl.$this->encoding;
  130. if(($wsdl=$cache->get($key))!==false)
  131. return $wsdl;
  132. }
  133. $generator=new CWsdlGenerator;
  134. $wsdl=$generator->generateWsdl($providerClass,$this->serviceUrl,$this->encoding);
  135. if(isset($key))
  136. $cache->set($key,$wsdl,$this->wsdlCacheDuration);
  137. return $wsdl;
  138. }
  139. /**
  140. * Handles the web service request.
  141. */
  142. public function run()
  143. {
  144. header('Content-Type: text/xml;charset='.$this->encoding);
  145. if(YII_DEBUG)
  146. ini_set("soap.wsdl_cache_enabled",0);
  147. $server=new SoapServer($this->wsdlUrl,$this->getOptions());
  148. Yii::app()->attachEventHandler('onError',array($this,'handleError'));
  149. try
  150. {
  151. if($this->persistence!==null)
  152. $server->setPersistence($this->persistence);
  153. if(is_string($this->provider))
  154. $provider=Yii::createComponent($this->provider);
  155. else
  156. $provider=$this->provider;
  157. if(method_exists($server,'setObject'))
  158. $server->setObject($provider);
  159. else
  160. $server->setClass('CSoapObjectWrapper',$provider);
  161. if($provider instanceof IWebServiceProvider)
  162. {
  163. if($provider->beforeWebMethod($this))
  164. {
  165. $server->handle();
  166. $provider->afterWebMethod($this);
  167. }
  168. }
  169. else
  170. $server->handle();
  171. }
  172. catch(Exception $e)
  173. {
  174. if($e->getCode()!==self::SOAP_ERROR) // non-PHP error
  175. {
  176. // only log for non-PHP-error case because application's error handler already logs it
  177. // php <5.2 doesn't support string conversion auto-magically
  178. Yii::log($e->__toString(),CLogger::LEVEL_ERROR,'application');
  179. }
  180. $message=$e->getMessage();
  181. if(YII_DEBUG)
  182. $message.=' ('.$e->getFile().':'.$e->getLine().")\n".$e->getTraceAsString();
  183. // We need to end application explicitly because of
  184. // http://bugs.php.net/bug.php?id=49513
  185. Yii::app()->onEndRequest(new CEvent($this));
  186. $server->fault(get_class($e),$message);
  187. exit(1);
  188. }
  189. }
  190. /**
  191. * @return string the currently requested method name. Empty if no method is being requested.
  192. */
  193. public function getMethodName()
  194. {
  195. if($this->_method===null)
  196. {
  197. if(isset($HTTP_RAW_POST_DATA))
  198. $request=$HTTP_RAW_POST_DATA;
  199. else
  200. $request=file_get_contents('php://input');
  201. if(preg_match('/<.*?:Body[^>]*>\s*<.*?:(\w+)/mi',$request,$matches))
  202. $this->_method=$matches[1];
  203. else
  204. $this->_method='';
  205. }
  206. return $this->_method;
  207. }
  208. /**
  209. * @return array options for creating SoapServer instance
  210. * @see http://www.php.net/manual/en/function.soap-soapserver-construct.php
  211. */
  212. protected function getOptions()
  213. {
  214. $options=array();
  215. if($this->soapVersion==='1.1')
  216. $options['soap_version']=SOAP_1_1;
  217. else if($this->soapVersion==='1.2')
  218. $options['soap_version']=SOAP_1_2;
  219. if($this->actor!==null)
  220. $options['actor']=$this->actor;
  221. $options['encoding']=$this->encoding;
  222. foreach($this->classMap as $type=>$className)
  223. {
  224. $className=Yii::import($className,true);
  225. if(is_int($type))
  226. $type=$className;
  227. $options['classmap'][$type]=$className;
  228. }
  229. return $options;
  230. }
  231. }
  232. /**
  233. * CSoapObjectWrapper is a wrapper class internally used when SoapServer::setObject() is not defined.
  234. *
  235. * @author Qiang Xue <qiang.xue@gmail.com>
  236. * @version $Id: CWebService.php 3277 2011-06-15 15:27:52Z qiang.xue $
  237. * @package system.web.services
  238. * @since 1.0.5
  239. */
  240. class CSoapObjectWrapper
  241. {
  242. /**
  243. * @var object the service provider
  244. */
  245. public $object=null;
  246. /**
  247. * Constructor.
  248. * @param object $object the service provider
  249. */
  250. public function __construct($object)
  251. {
  252. $this->object=$object;
  253. }
  254. /**
  255. * PHP __call magic method.
  256. * This method calls the service provider to execute the actual logic.
  257. * @param string $name method name
  258. * @param array $arguments method arguments
  259. * @return mixed method return value
  260. */
  261. public function __call($name,$arguments)
  262. {
  263. return call_user_func_array(array($this->object,$name),$arguments);
  264. }
  265. }