PageRenderTime 43ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/demo/yii/web/services/CWebService.php

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