PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/yii/framework/web/services/CWebService.php

https://bitbucket.org/ddonthula/zurmouser
PHP | 291 lines | 147 code | 18 blank | 126 comment | 23 complexity | 4f91f2b89736b9d9b5f91ed1672728e3 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-2-Clause, GPL-2.0, GPL-3.0, BSD-3-Clause, LGPL-3.0
  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. However WSDL generator
  17. * could be customized through {@link generatorConfig} property.
  18. *
  19. * To generate the WSDL based on doc comment blocks in the service provider class,
  20. * call {@link generateWsdl} or {@link renderWsdl}. To process the web service
  21. * requests, call {@link run}.
  22. *
  23. * @property string $methodName The currently requested method name. Empty if no method is being requested.
  24. *
  25. * @author Qiang Xue <qiang.xue@gmail.com>
  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. /**
  80. * @var string|array WSDL generator configuration. This property may be useful in purpose of enhancing features
  81. * of the standard {@link CWsdlGenerator} class by extending it. For example, some developers may need support
  82. * of the <code>xsd:xsd:base64Binary</code> elements. Another use case is to change initial values
  83. * at instantiation of the default {@link CWsdlGenerator}. The value of this property will be passed
  84. * to {@link Yii::createComponent} to create the generator object. Default value is 'CWsdlGenerator'.
  85. * @since 1.1.12
  86. */
  87. public $generatorConfig='CWsdlGenerator';
  88. private $_method;
  89. /**
  90. * Constructor.
  91. * @param mixed $provider the web service provider class name or object
  92. * @param string $wsdlUrl the URL for WSDL. This is required by {@link run()}.
  93. * @param string $serviceUrl the URL for the Web service. This is required by {@link generateWsdl()} and {@link renderWsdl()}.
  94. */
  95. public function __construct($provider,$wsdlUrl,$serviceUrl)
  96. {
  97. $this->provider=$provider;
  98. $this->wsdlUrl=$wsdlUrl;
  99. $this->serviceUrl=$serviceUrl;
  100. }
  101. /**
  102. * The PHP error handler.
  103. * @param CErrorEvent $event the PHP error event
  104. */
  105. public function handleError($event)
  106. {
  107. $event->handled=true;
  108. $message=$event->message;
  109. if(YII_DEBUG)
  110. {
  111. $trace=debug_backtrace();
  112. if(isset($trace[2]) && isset($trace[2]['file']) && isset($trace[2]['line']))
  113. $message.=' ('.$trace[2]['file'].':'.$trace[2]['line'].')';
  114. }
  115. throw new CException($message,self::SOAP_ERROR);
  116. }
  117. /**
  118. * Generates and displays the WSDL as defined by the provider.
  119. * @see generateWsdl
  120. */
  121. public function renderWsdl()
  122. {
  123. $wsdl=$this->generateWsdl();
  124. header('Content-Type: text/xml;charset='.$this->encoding);
  125. header('Content-Length: '.(function_exists('mb_strlen') ? mb_strlen($wsdl,'8bit') : strlen($wsdl)));
  126. echo $wsdl;
  127. }
  128. /**
  129. * Generates the WSDL as defined by the provider.
  130. * The cached version may be used if the WSDL is found valid in cache.
  131. * @return string the generated WSDL
  132. * @see wsdlCacheDuration
  133. */
  134. public function generateWsdl()
  135. {
  136. $providerClass=is_object($this->provider) ? get_class($this->provider) : Yii::import($this->provider,true);
  137. if($this->wsdlCacheDuration>0 && $this->cacheID!==false && ($cache=Yii::app()->getComponent($this->cacheID))!==null)
  138. {
  139. $key='Yii.CWebService.'.$providerClass.$this->serviceUrl.$this->encoding;
  140. if(($wsdl=$cache->get($key))!==false)
  141. return $wsdl;
  142. }
  143. $generator=Yii::createComponent($this->generatorConfig);
  144. $wsdl=$generator->generateWsdl($providerClass,$this->serviceUrl,$this->encoding);
  145. if(isset($key))
  146. $cache->set($key,$wsdl,$this->wsdlCacheDuration);
  147. return $wsdl;
  148. }
  149. /**
  150. * Handles the web service request.
  151. */
  152. public function run()
  153. {
  154. header('Content-Type: text/xml;charset='.$this->encoding);
  155. if(YII_DEBUG)
  156. ini_set("soap.wsdl_cache_enabled",0);
  157. $server=new SoapServer($this->wsdlUrl,$this->getOptions());
  158. Yii::app()->attachEventHandler('onError',array($this,'handleError'));
  159. try
  160. {
  161. if($this->persistence!==null)
  162. $server->setPersistence($this->persistence);
  163. if(is_string($this->provider))
  164. $provider=Yii::createComponent($this->provider);
  165. else
  166. $provider=$this->provider;
  167. if(method_exists($server,'setObject'))
  168. $server->setObject($provider);
  169. else
  170. $server->setClass('CSoapObjectWrapper',$provider);
  171. if($provider instanceof IWebServiceProvider)
  172. {
  173. if($provider->beforeWebMethod($this))
  174. {
  175. $server->handle();
  176. $provider->afterWebMethod($this);
  177. }
  178. }
  179. else
  180. $server->handle();
  181. }
  182. catch(Exception $e)
  183. {
  184. if($e->getCode()!==self::SOAP_ERROR) // non-PHP error
  185. {
  186. // only log for non-PHP-error case because application's error handler already logs it
  187. // php <5.2 doesn't support string conversion auto-magically
  188. Yii::log($e->__toString(),CLogger::LEVEL_ERROR,'application');
  189. }
  190. $message=$e->getMessage();
  191. if(YII_DEBUG)
  192. $message.=' ('.$e->getFile().':'.$e->getLine().")\n".$e->getTraceAsString();
  193. // We need to end application explicitly because of
  194. // http://bugs.php.net/bug.php?id=49513
  195. Yii::app()->onEndRequest(new CEvent($this));
  196. $server->fault(get_class($e),$message);
  197. exit(1);
  198. }
  199. }
  200. /**
  201. * @return string the currently requested method name. Empty if no method is being requested.
  202. */
  203. public function getMethodName()
  204. {
  205. if($this->_method===null)
  206. {
  207. if(isset($HTTP_RAW_POST_DATA))
  208. $request=$HTTP_RAW_POST_DATA;
  209. else
  210. $request=file_get_contents('php://input');
  211. if(preg_match('/<.*?:Body[^>]*>\s*<.*?:(\w+)/mi',$request,$matches))
  212. $this->_method=$matches[1];
  213. else
  214. $this->_method='';
  215. }
  216. return $this->_method;
  217. }
  218. /**
  219. * @return array options for creating SoapServer instance
  220. * @see http://www.php.net/manual/en/function.soap-soapserver-construct.php
  221. */
  222. protected function getOptions()
  223. {
  224. $options=array();
  225. if($this->soapVersion==='1.1')
  226. $options['soap_version']=SOAP_1_1;
  227. elseif($this->soapVersion==='1.2')
  228. $options['soap_version']=SOAP_1_2;
  229. if($this->actor!==null)
  230. $options['actor']=$this->actor;
  231. $options['encoding']=$this->encoding;
  232. foreach($this->classMap as $type=>$className)
  233. {
  234. $className=Yii::import($className,true);
  235. if(is_int($type))
  236. $type=$className;
  237. $options['classmap'][$type]=$className;
  238. }
  239. return $options;
  240. }
  241. }
  242. /**
  243. * CSoapObjectWrapper is a wrapper class internally used when SoapServer::setObject() is not defined.
  244. *
  245. * @author Qiang Xue <qiang.xue@gmail.com>
  246. * @package system.web.services
  247. */
  248. class CSoapObjectWrapper
  249. {
  250. /**
  251. * @var object the service provider
  252. */
  253. public $object=null;
  254. /**
  255. * Constructor.
  256. * @param object $object the service provider
  257. */
  258. public function __construct($object)
  259. {
  260. $this->object=$object;
  261. }
  262. /**
  263. * PHP __call magic method.
  264. * This method calls the service provider to execute the actual logic.
  265. * @param string $name method name
  266. * @param array $arguments method arguments
  267. * @return mixed method return value
  268. */
  269. public function __call($name,$arguments)
  270. {
  271. return call_user_func_array(array($this->object,$name),$arguments);
  272. }
  273. }