PageRenderTime 40ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/zendframework/zend-json/src/Server/Smd/Service.php

https://gitlab.com/galaxy-pidev/AllForDealWeb
PHP | 465 lines | 388 code | 14 blank | 63 comment | 7 complexity | 2f41d184066dc6e3404c51207be29a9e MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. */
  9. namespace Zend\Json\Server\Smd;
  10. use Zend\Json\Server\Exception\InvalidArgumentException;
  11. use Zend\Json\Server\Smd;
  12. /**
  13. * Create Service Mapping Description for a method
  14. *
  15. * @todo Revised method regex to allow NS; however, should SMD be revised to strip PHP NS instead when attaching functions?
  16. */
  17. class Service
  18. {
  19. /**#@+
  20. * Service metadata
  21. * @var string
  22. */
  23. protected $envelope = Smd::ENV_JSONRPC_1;
  24. protected $name;
  25. protected $return;
  26. protected $target;
  27. protected $transport = 'POST';
  28. /**#@-*/
  29. /**
  30. * Allowed envelope types
  31. * @var array
  32. */
  33. protected $envelopeTypes = [
  34. Smd::ENV_JSONRPC_1,
  35. Smd::ENV_JSONRPC_2,
  36. ];
  37. /**
  38. * Regex for names
  39. * @var string
  40. *
  41. * @link http://php.net/manual/en/language.oop5.basic.php
  42. * @link http://www.jsonrpc.org/specification#request_object
  43. */
  44. protected $nameRegex = '/^(?!^rpc\.)[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff\.\\\]*$/';
  45. /**
  46. * Parameter option types
  47. * @var array
  48. */
  49. protected $paramOptionTypes = [
  50. 'name' => 'is_string',
  51. 'optional' => 'is_bool',
  52. 'default' => null,
  53. 'description' => 'is_string',
  54. ];
  55. /**
  56. * Service params
  57. * @var array
  58. */
  59. protected $params = [];
  60. /**
  61. * Mapping of parameter types to JSON-RPC types
  62. * @var array
  63. */
  64. protected $paramMap = [
  65. 'any' => 'any',
  66. 'arr' => 'array',
  67. 'array' => 'array',
  68. 'assoc' => 'object',
  69. 'bool' => 'boolean',
  70. 'boolean' => 'boolean',
  71. 'dbl' => 'float',
  72. 'double' => 'float',
  73. 'false' => 'boolean',
  74. 'float' => 'float',
  75. 'hash' => 'object',
  76. 'integer' => 'integer',
  77. 'int' => 'integer',
  78. 'mixed' => 'any',
  79. 'nil' => 'null',
  80. 'null' => 'null',
  81. 'object' => 'object',
  82. 'string' => 'string',
  83. 'str' => 'string',
  84. 'struct' => 'object',
  85. 'true' => 'boolean',
  86. 'void' => 'null',
  87. ];
  88. /**
  89. * Allowed transport types
  90. * @var array
  91. */
  92. protected $transportTypes = [
  93. 'POST',
  94. ];
  95. /**
  96. * Constructor
  97. *
  98. * @param string|array $spec
  99. * @throws InvalidArgumentException if no name provided
  100. */
  101. public function __construct($spec)
  102. {
  103. if (is_string($spec)) {
  104. $this->setName($spec);
  105. } elseif (is_array($spec)) {
  106. $this->setOptions($spec);
  107. }
  108. if (null == $this->getName()) {
  109. throw new InvalidArgumentException('SMD service description requires a name; none provided');
  110. }
  111. }
  112. /**
  113. * Set object state
  114. *
  115. * @param array $options
  116. * @return Service
  117. */
  118. public function setOptions(array $options)
  119. {
  120. $methods = get_class_methods($this);
  121. foreach ($options as $key => $value) {
  122. if ('options' == strtolower($key)) {
  123. continue;
  124. }
  125. $method = 'set' . ucfirst($key);
  126. if (in_array($method, $methods)) {
  127. $this->$method($value);
  128. }
  129. }
  130. return $this;
  131. }
  132. /**
  133. * Set service name
  134. *
  135. * @param string $name
  136. * @return Service
  137. * @throws InvalidArgumentException
  138. */
  139. public function setName($name)
  140. {
  141. $name = (string) $name;
  142. if (!preg_match($this->nameRegex, $name)) {
  143. throw new InvalidArgumentException("Invalid name '{$name} provided for service; must follow PHP method naming conventions");
  144. }
  145. $this->name = $name;
  146. return $this;
  147. }
  148. /**
  149. * Retrieve name
  150. *
  151. * @return string
  152. */
  153. public function getName()
  154. {
  155. return $this->name;
  156. }
  157. /**
  158. * Set Transport
  159. *
  160. * Currently limited to POST
  161. *
  162. * @param string $transport
  163. * @throws InvalidArgumentException
  164. * @return Service
  165. */
  166. public function setTransport($transport)
  167. {
  168. if (!in_array($transport, $this->transportTypes)) {
  169. throw new InvalidArgumentException("Invalid transport '{$transport}'; please select one of (" . implode(', ', $this->transportTypes) . ')');
  170. }
  171. $this->transport = $transport;
  172. return $this;
  173. }
  174. /**
  175. * Get transport
  176. *
  177. * @return string
  178. */
  179. public function getTransport()
  180. {
  181. return $this->transport;
  182. }
  183. /**
  184. * Set service target
  185. *
  186. * @param string $target
  187. * @return Service
  188. */
  189. public function setTarget($target)
  190. {
  191. $this->target = (string) $target;
  192. return $this;
  193. }
  194. /**
  195. * Get service target
  196. *
  197. * @return string
  198. */
  199. public function getTarget()
  200. {
  201. return $this->target;
  202. }
  203. /**
  204. * Set envelope type
  205. *
  206. * @param string $envelopeType
  207. * @throws InvalidArgumentException
  208. * @return Service
  209. */
  210. public function setEnvelope($envelopeType)
  211. {
  212. if (!in_array($envelopeType, $this->envelopeTypes)) {
  213. throw new InvalidArgumentException("Invalid envelope type '{$envelopeType}'; please specify one of (" . implode(', ', $this->envelopeTypes) . ')');
  214. }
  215. $this->envelope = $envelopeType;
  216. return $this;
  217. }
  218. /**
  219. * Get envelope type
  220. *
  221. * @return string
  222. */
  223. public function getEnvelope()
  224. {
  225. return $this->envelope;
  226. }
  227. /**
  228. * Add a parameter to the service
  229. *
  230. * @param string|array $type
  231. * @param array $options
  232. * @param int|null $order
  233. * @throws InvalidArgumentException
  234. * @return Service
  235. */
  236. public function addParam($type, array $options = [], $order = null)
  237. {
  238. if (is_string($type)) {
  239. $type = $this->_validateParamType($type);
  240. } elseif (is_array($type)) {
  241. foreach ($type as $key => $paramType) {
  242. $type[$key] = $this->_validateParamType($paramType);
  243. }
  244. } else {
  245. throw new InvalidArgumentException('Invalid param type provided');
  246. }
  247. $paramOptions = [
  248. 'type' => $type,
  249. ];
  250. foreach ($options as $key => $value) {
  251. if (in_array($key, array_keys($this->paramOptionTypes))) {
  252. if (null !== ($callback = $this->paramOptionTypes[$key])) {
  253. if (!$callback($value)) {
  254. continue;
  255. }
  256. }
  257. $paramOptions[$key] = $value;
  258. }
  259. }
  260. $this->params[] = [
  261. 'param' => $paramOptions,
  262. 'order' => $order,
  263. ];
  264. return $this;
  265. }
  266. /**
  267. * Add params
  268. *
  269. * Each param should be an array, and should include the key 'type'.
  270. *
  271. * @param array $params
  272. * @return Service
  273. */
  274. public function addParams(array $params)
  275. {
  276. ksort($params);
  277. foreach ($params as $options) {
  278. if (!is_array($options)) {
  279. continue;
  280. }
  281. if (!array_key_exists('type', $options)) {
  282. continue;
  283. }
  284. $type = $options['type'];
  285. $order = (array_key_exists('order', $options)) ? $options['order'] : null;
  286. $this->addParam($type, $options, $order);
  287. }
  288. return $this;
  289. }
  290. /**
  291. * Overwrite all parameters
  292. *
  293. * @param array $params
  294. * @return Service
  295. */
  296. public function setParams(array $params)
  297. {
  298. $this->params = [];
  299. return $this->addParams($params);
  300. }
  301. /**
  302. * Get all parameters
  303. *
  304. * Returns all params in specified order.
  305. *
  306. * @return array
  307. */
  308. public function getParams()
  309. {
  310. $params = [];
  311. $index = 0;
  312. foreach ($this->params as $param) {
  313. if (null === $param['order']) {
  314. if (array_search($index, array_keys($params), true)) {
  315. ++$index;
  316. }
  317. $params[$index] = $param['param'];
  318. ++$index;
  319. } else {
  320. $params[$param['order']] = $param['param'];
  321. }
  322. }
  323. ksort($params);
  324. return $params;
  325. }
  326. /**
  327. * Set return type
  328. *
  329. * @param string|array $type
  330. * @throws InvalidArgumentException
  331. * @return Service
  332. */
  333. public function setReturn($type)
  334. {
  335. if (is_string($type)) {
  336. $type = $this->_validateParamType($type, true);
  337. } elseif (is_array($type)) {
  338. foreach ($type as $key => $returnType) {
  339. $type[$key] = $this->_validateParamType($returnType, true);
  340. }
  341. } else {
  342. throw new InvalidArgumentException("Invalid param type provided ('" . gettype($type) . "')");
  343. }
  344. $this->return = $type;
  345. return $this;
  346. }
  347. /**
  348. * Get return type
  349. *
  350. * @return string|array
  351. */
  352. public function getReturn()
  353. {
  354. return $this->return;
  355. }
  356. /**
  357. * Cast service description to array
  358. *
  359. * @return array
  360. */
  361. public function toArray()
  362. {
  363. $envelope = $this->getEnvelope();
  364. $target = $this->getTarget();
  365. $transport = $this->getTransport();
  366. $parameters = $this->getParams();
  367. $returns = $this->getReturn();
  368. $name = $this->getName();
  369. if (empty($target)) {
  370. return compact('envelope', 'transport', 'name', 'parameters', 'returns');
  371. }
  372. return compact('envelope', 'target', 'transport', 'name', 'parameters', 'returns');
  373. }
  374. /**
  375. * Return JSON encoding of service
  376. *
  377. * @return string
  378. */
  379. public function toJson()
  380. {
  381. $service = [$this->getName() => $this->toArray()];
  382. return \Zend\Json\Json::encode($service);
  383. }
  384. /**
  385. * Cast to string
  386. *
  387. * @return string
  388. */
  389. public function __toString()
  390. {
  391. return $this->toJson();
  392. }
  393. /**
  394. * Validate parameter type
  395. *
  396. * @param string $type
  397. * @param bool $isReturn
  398. * @return string
  399. * @throws InvalidArgumentException
  400. */
  401. protected function _validateParamType($type, $isReturn = false)
  402. {
  403. if (!is_string($type)) {
  404. throw new InvalidArgumentException("Invalid param type provided ('{$type}')");
  405. }
  406. if (!array_key_exists($type, $this->paramMap)) {
  407. $type = 'object';
  408. }
  409. $paramType = $this->paramMap[$type];
  410. if (!$isReturn && ('null' == $paramType)) {
  411. throw new InvalidArgumentException("Invalid param type provided ('{$type}')");
  412. }
  413. return $paramType;
  414. }
  415. }