|
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_Json |
|
17 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
18 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
19 */ |
|
20 |
|
21 /** |
|
22 * @see Zend_Json_Server_Smd |
|
23 */ |
|
24 require_once 'Zend/Json/Server/Smd.php'; |
|
25 |
|
26 /** |
|
27 * Create Service Mapping Description for a method |
|
28 * |
|
29 * @package Zend_Json |
|
30 * @subpackage Server |
|
31 * @version $Id: Service.php 20096 2010-01-06 02:05:09Z bkarwin $ |
|
32 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
33 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
34 */ |
|
35 class Zend_Json_Server_Smd_Service |
|
36 { |
|
37 /**#@+ |
|
38 * Service metadata |
|
39 * @var string |
|
40 */ |
|
41 protected $_envelope = Zend_Json_Server_Smd::ENV_JSONRPC_1; |
|
42 protected $_name; |
|
43 protected $_return; |
|
44 protected $_target; |
|
45 protected $_transport = 'POST'; |
|
46 /**#@-*/ |
|
47 |
|
48 /** |
|
49 * Allowed envelope types |
|
50 * @var array |
|
51 */ |
|
52 protected $_envelopeTypes = array( |
|
53 Zend_Json_Server_Smd::ENV_JSONRPC_1, |
|
54 Zend_Json_Server_Smd::ENV_JSONRPC_2, |
|
55 ); |
|
56 |
|
57 /** |
|
58 * Regex for names |
|
59 * @var string |
|
60 */ |
|
61 protected $_nameRegex = '/^[a-z][a-z0-9._]+$/i'; |
|
62 |
|
63 /** |
|
64 * Parameter option types |
|
65 * @var array |
|
66 */ |
|
67 protected $_paramOptionTypes = array( |
|
68 'name' => 'is_string', |
|
69 'optional' => 'is_bool', |
|
70 'default' => null, |
|
71 'description' => 'is_string', |
|
72 ); |
|
73 |
|
74 /** |
|
75 * Service params |
|
76 * @var array |
|
77 */ |
|
78 protected $_params = array(); |
|
79 |
|
80 /** |
|
81 * Mapping of parameter types to JSON-RPC types |
|
82 * @var array |
|
83 */ |
|
84 protected $_paramMap = array( |
|
85 'any' => 'any', |
|
86 'arr' => 'array', |
|
87 'array' => 'array', |
|
88 'assoc' => 'object', |
|
89 'bool' => 'boolean', |
|
90 'boolean' => 'boolean', |
|
91 'dbl' => 'float', |
|
92 'double' => 'float', |
|
93 'false' => 'boolean', |
|
94 'float' => 'float', |
|
95 'hash' => 'object', |
|
96 'integer' => 'integer', |
|
97 'int' => 'integer', |
|
98 'mixed' => 'any', |
|
99 'nil' => 'null', |
|
100 'null' => 'null', |
|
101 'object' => 'object', |
|
102 'string' => 'string', |
|
103 'str' => 'string', |
|
104 'struct' => 'object', |
|
105 'true' => 'boolean', |
|
106 'void' => 'null', |
|
107 ); |
|
108 |
|
109 /** |
|
110 * Allowed transport types |
|
111 * @var array |
|
112 */ |
|
113 protected $_transportTypes = array( |
|
114 'POST', |
|
115 ); |
|
116 |
|
117 /** |
|
118 * Constructor |
|
119 * |
|
120 * @param string|array $spec |
|
121 * @return void |
|
122 * @throws Zend_Json_Server_Exception if no name provided |
|
123 */ |
|
124 public function __construct($spec) |
|
125 { |
|
126 if (is_string($spec)) { |
|
127 $this->setName($spec); |
|
128 } elseif (is_array($spec)) { |
|
129 $this->setOptions($spec); |
|
130 } |
|
131 |
|
132 if (null == $this->getName()) { |
|
133 require_once 'Zend/Json/Server/Exception.php'; |
|
134 throw new Zend_Json_Server_Exception('SMD service description requires a name; none provided'); |
|
135 } |
|
136 } |
|
137 |
|
138 /** |
|
139 * Set object state |
|
140 * |
|
141 * @param array $options |
|
142 * @return Zend_Json_Server_Smd_Service |
|
143 */ |
|
144 public function setOptions(array $options) |
|
145 { |
|
146 $methods = get_class_methods($this); |
|
147 foreach ($options as $key => $value) { |
|
148 if ('options' == strtolower($key)) { |
|
149 continue; |
|
150 } |
|
151 $method = 'set' . ucfirst($key); |
|
152 if (in_array($method, $methods)) { |
|
153 $this->$method($value); |
|
154 } |
|
155 } |
|
156 return $this; |
|
157 } |
|
158 |
|
159 /** |
|
160 * Set service name |
|
161 * |
|
162 * @param string $name |
|
163 * @return Zend_Json_Server_Smd_Service |
|
164 * @throws Zend_Json_Server_Exception |
|
165 */ |
|
166 public function setName($name) |
|
167 { |
|
168 $name = (string) $name; |
|
169 if (!preg_match($this->_nameRegex, $name)) { |
|
170 require_once 'Zend/Json/Server/Exception.php'; |
|
171 throw new Zend_Json_Server_Exception(sprintf('Invalid name "%s" provided for service; must follow PHP method naming conventions', $name)); |
|
172 } |
|
173 $this->_name = $name; |
|
174 return $this; |
|
175 } |
|
176 |
|
177 /** |
|
178 * Retrieve name |
|
179 * |
|
180 * @return string |
|
181 */ |
|
182 public function getName() |
|
183 { |
|
184 return $this->_name; |
|
185 } |
|
186 |
|
187 /** |
|
188 * Set Transport |
|
189 * |
|
190 * Currently limited to POST |
|
191 * |
|
192 * @param string $transport |
|
193 * @return Zend_Json_Server_Smd_Service |
|
194 */ |
|
195 public function setTransport($transport) |
|
196 { |
|
197 if (!in_array($transport, $this->_transportTypes)) { |
|
198 require_once 'Zend/Json/Server/Exception.php'; |
|
199 throw new Zend_Json_Server_Exception(sprintf('Invalid transport "%s"; please select one of (%s)', $transport, implode(', ', $this->_transportTypes))); |
|
200 } |
|
201 |
|
202 $this->_transport = $transport; |
|
203 return $this; |
|
204 } |
|
205 |
|
206 /** |
|
207 * Get transport |
|
208 * |
|
209 * @return string |
|
210 */ |
|
211 public function getTransport() |
|
212 { |
|
213 return $this->_transport; |
|
214 } |
|
215 |
|
216 /** |
|
217 * Set service target |
|
218 * |
|
219 * @param string $target |
|
220 * @return Zend_Json_Server_Smd_Service |
|
221 */ |
|
222 public function setTarget($target) |
|
223 { |
|
224 $this->_target = (string) $target; |
|
225 return $this; |
|
226 } |
|
227 |
|
228 /** |
|
229 * Get service target |
|
230 * |
|
231 * @return string |
|
232 */ |
|
233 public function getTarget() |
|
234 { |
|
235 return $this->_target; |
|
236 } |
|
237 |
|
238 /** |
|
239 * Set envelope type |
|
240 * |
|
241 * @param string $envelopeType |
|
242 * @return Zend_Json_Server_Smd_Service |
|
243 */ |
|
244 public function setEnvelope($envelopeType) |
|
245 { |
|
246 if (!in_array($envelopeType, $this->_envelopeTypes)) { |
|
247 require_once 'Zend/Json/Server/Exception.php'; |
|
248 throw new Zend_Json_Server_Exception(sprintf('Invalid envelope type "%s"; please specify one of (%s)', $envelopeType, implode(', ', $this->_envelopeTypes))); |
|
249 } |
|
250 |
|
251 $this->_envelope = $envelopeType; |
|
252 return $this; |
|
253 } |
|
254 |
|
255 /** |
|
256 * Get envelope type |
|
257 * |
|
258 * @return string |
|
259 */ |
|
260 public function getEnvelope() |
|
261 { |
|
262 return $this->_envelope; |
|
263 } |
|
264 |
|
265 /** |
|
266 * Add a parameter to the service |
|
267 * |
|
268 * @param string|array $type |
|
269 * @param array $options |
|
270 * @param int|null $order |
|
271 * @return Zend_Json_Server_Smd_Service |
|
272 */ |
|
273 public function addParam($type, array $options = array(), $order = null) |
|
274 { |
|
275 if (is_string($type)) { |
|
276 $type = $this->_validateParamType($type); |
|
277 } elseif (is_array($type)) { |
|
278 foreach ($type as $key => $paramType) { |
|
279 $type[$key] = $this->_validateParamType($paramType); |
|
280 } |
|
281 } else { |
|
282 require_once 'Zend/Json/Server/Exception.php'; |
|
283 throw new Zend_Json_Server_Exception('Invalid param type provided'); |
|
284 } |
|
285 |
|
286 $paramOptions = array( |
|
287 'type' => $type, |
|
288 ); |
|
289 foreach ($options as $key => $value) { |
|
290 if (in_array($key, array_keys($this->_paramOptionTypes))) { |
|
291 if (null !== ($callback = $this->_paramOptionTypes[$key])) { |
|
292 if (!$callback($value)) { |
|
293 continue; |
|
294 } |
|
295 } |
|
296 $paramOptions[$key] = $value; |
|
297 } |
|
298 } |
|
299 |
|
300 $this->_params[] = array( |
|
301 'param' => $paramOptions, |
|
302 'order' => $order, |
|
303 ); |
|
304 |
|
305 return $this; |
|
306 } |
|
307 |
|
308 /** |
|
309 * Add params |
|
310 * |
|
311 * Each param should be an array, and should include the key 'type'. |
|
312 * |
|
313 * @param array $params |
|
314 * @return Zend_Json_Server_Smd_Service |
|
315 */ |
|
316 public function addParams(array $params) |
|
317 { |
|
318 ksort($params); |
|
319 foreach ($params as $options) { |
|
320 if (!is_array($options)) { |
|
321 continue; |
|
322 } |
|
323 if (!array_key_exists('type', $options)) { |
|
324 continue; |
|
325 } |
|
326 $type = $options['type']; |
|
327 $order = (array_key_exists('order', $options)) ? $options['order'] : null; |
|
328 $this->addParam($type, $options, $order); |
|
329 } |
|
330 return $this; |
|
331 } |
|
332 |
|
333 /** |
|
334 * Overwrite all parameters |
|
335 * |
|
336 * @param array $params |
|
337 * @return Zend_Json_Server_Smd_Service |
|
338 */ |
|
339 public function setParams(array $params) |
|
340 { |
|
341 $this->_params = array(); |
|
342 return $this->addParams($params); |
|
343 } |
|
344 |
|
345 /** |
|
346 * Get all parameters |
|
347 * |
|
348 * Returns all params in specified order. |
|
349 * |
|
350 * @return array |
|
351 */ |
|
352 public function getParams() |
|
353 { |
|
354 $params = array(); |
|
355 $index = 0; |
|
356 foreach ($this->_params as $param) { |
|
357 if (null === $param['order']) { |
|
358 if (array_search($index, array_keys($params), true)) { |
|
359 ++$index; |
|
360 } |
|
361 $params[$index] = $param['param']; |
|
362 ++$index; |
|
363 } else { |
|
364 $params[$param['order']] = $param['param']; |
|
365 } |
|
366 } |
|
367 ksort($params); |
|
368 return $params; |
|
369 } |
|
370 |
|
371 /** |
|
372 * Set return type |
|
373 * |
|
374 * @param string|array $type |
|
375 * @return Zend_Json_Server_Smd_Service |
|
376 */ |
|
377 public function setReturn($type) |
|
378 { |
|
379 if (is_string($type)) { |
|
380 $type = $this->_validateParamType($type, true); |
|
381 } elseif (is_array($type)) { |
|
382 foreach ($type as $key => $returnType) { |
|
383 $type[$key] = $this->_validateParamType($returnType, true); |
|
384 } |
|
385 } else { |
|
386 require_once 'Zend/Json/Server/Exception.php'; |
|
387 throw new Zend_Json_Server_Exception('Invalid param type provided ("' . gettype($type) .'")'); |
|
388 } |
|
389 $this->_return = $type; |
|
390 return $this; |
|
391 } |
|
392 |
|
393 /** |
|
394 * Get return type |
|
395 * |
|
396 * @return string|array |
|
397 */ |
|
398 public function getReturn() |
|
399 { |
|
400 return $this->_return; |
|
401 } |
|
402 |
|
403 /** |
|
404 * Cast service description to array |
|
405 * |
|
406 * @return array |
|
407 */ |
|
408 public function toArray() |
|
409 { |
|
410 $name = $this->getName(); |
|
411 $envelope = $this->getEnvelope(); |
|
412 $target = $this->getTarget(); |
|
413 $transport = $this->getTransport(); |
|
414 $parameters = $this->getParams(); |
|
415 $returns = $this->getReturn(); |
|
416 |
|
417 if (empty($target)) { |
|
418 return compact('envelope', 'transport', 'parameters', 'returns'); |
|
419 } |
|
420 |
|
421 return $paramInfo = compact('envelope', 'target', 'transport', 'parameters', 'returns'); |
|
422 } |
|
423 |
|
424 /** |
|
425 * Return JSON encoding of service |
|
426 * |
|
427 * @return string |
|
428 */ |
|
429 public function toJson() |
|
430 { |
|
431 $service = array($this->getName() => $this->toArray()); |
|
432 |
|
433 require_once 'Zend/Json.php'; |
|
434 return Zend_Json::encode($service); |
|
435 } |
|
436 |
|
437 /** |
|
438 * Cast to string |
|
439 * |
|
440 * @return string |
|
441 */ |
|
442 public function __toString() |
|
443 { |
|
444 return $this->toJson(); |
|
445 } |
|
446 |
|
447 /** |
|
448 * Validate parameter type |
|
449 * |
|
450 * @param string $type |
|
451 * @return true |
|
452 * @throws Zend_Json_Server_Exception |
|
453 */ |
|
454 protected function _validateParamType($type, $isReturn = false) |
|
455 { |
|
456 if (!is_string($type)) { |
|
457 require_once 'Zend/Json/Server/Exception.php'; |
|
458 throw new Zend_Json_Server_Exception('Invalid param type provided ("' . $type .'")'); |
|
459 } |
|
460 |
|
461 if (!array_key_exists($type, $this->_paramMap)) { |
|
462 $type = 'object'; |
|
463 } |
|
464 |
|
465 $paramType = $this->_paramMap[$type]; |
|
466 if (!$isReturn && ('null' == $paramType)) { |
|
467 require_once 'Zend/Json/Server/Exception.php'; |
|
468 throw new Zend_Json_Server_Exception('Invalid param type provided ("' . $type . '")'); |
|
469 } |
|
470 |
|
471 return $paramType; |
|
472 } |
|
473 } |