|
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 * @subpackage Server |
|
18 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
19 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
20 * @version $Id: Smd.php 20096 2010-01-06 02:05:09Z bkarwin $ |
|
21 */ |
|
22 |
|
23 /** |
|
24 * @category Zend |
|
25 * @package Zend_Json |
|
26 * @subpackage Server |
|
27 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
28 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
29 */ |
|
30 class Zend_Json_Server_Smd |
|
31 { |
|
32 const ENV_JSONRPC_1 = 'JSON-RPC-1.0'; |
|
33 const ENV_JSONRPC_2 = 'JSON-RPC-2.0'; |
|
34 const SMD_VERSION = '2.0'; |
|
35 |
|
36 /** |
|
37 * Content type |
|
38 * @var string |
|
39 */ |
|
40 protected $_contentType = 'application/json'; |
|
41 |
|
42 /** |
|
43 * Content type regex |
|
44 * @var string |
|
45 */ |
|
46 protected $_contentTypeRegex = '#[a-z]+/[a-z][a-z-]+#i'; |
|
47 |
|
48 /** |
|
49 * Service description |
|
50 * @var string |
|
51 */ |
|
52 protected $_description; |
|
53 |
|
54 /** |
|
55 * Generate Dojo-compatible SMD |
|
56 * @var bool |
|
57 */ |
|
58 protected $_dojoCompatible = false; |
|
59 |
|
60 /** |
|
61 * Current envelope |
|
62 * @var string |
|
63 */ |
|
64 protected $_envelope = self::ENV_JSONRPC_1; |
|
65 |
|
66 /** |
|
67 * Allowed envelope types |
|
68 * @var array |
|
69 */ |
|
70 protected $_envelopeTypes = array( |
|
71 self::ENV_JSONRPC_1, |
|
72 self::ENV_JSONRPC_2, |
|
73 ); |
|
74 |
|
75 /** |
|
76 * Service id |
|
77 * @var string |
|
78 */ |
|
79 protected $_id; |
|
80 |
|
81 /** |
|
82 * Services offerred |
|
83 * @var array |
|
84 */ |
|
85 protected $_services = array(); |
|
86 |
|
87 /** |
|
88 * Service target |
|
89 * @var string |
|
90 */ |
|
91 protected $_target; |
|
92 |
|
93 /** |
|
94 * Global transport |
|
95 * @var string |
|
96 */ |
|
97 protected $_transport = 'POST'; |
|
98 |
|
99 /** |
|
100 * Allowed transport types |
|
101 * @var array |
|
102 */ |
|
103 protected $_transportTypes = array('POST'); |
|
104 |
|
105 /** |
|
106 * Set object state via options |
|
107 * |
|
108 * @param array $options |
|
109 * @return Zend_Json_Server_Smd |
|
110 */ |
|
111 public function setOptions(array $options) |
|
112 { |
|
113 $methods = get_class_methods($this); |
|
114 foreach ($options as $key => $value) { |
|
115 $method = 'set' . ucfirst($key); |
|
116 if (in_array($method, $methods)) { |
|
117 $this->$method($value); |
|
118 } |
|
119 } |
|
120 return $this; |
|
121 } |
|
122 |
|
123 /** |
|
124 * Set transport |
|
125 * |
|
126 * @param string $transport |
|
127 * @return Zend_Json_Server_Smd |
|
128 */ |
|
129 public function setTransport($transport) |
|
130 { |
|
131 if (!in_array($transport, $this->_transportTypes)) { |
|
132 require_once 'Zend/Json/Server/Exception.php'; |
|
133 throw new Zend_Json_Server_Exception(sprintf('Invalid transport "%s" specified', $transport)); |
|
134 } |
|
135 $this->_transport = $transport; |
|
136 return $this; |
|
137 } |
|
138 |
|
139 /** |
|
140 * Get transport |
|
141 * |
|
142 * @return string |
|
143 */ |
|
144 public function getTransport() |
|
145 { |
|
146 return $this->_transport; |
|
147 } |
|
148 |
|
149 /** |
|
150 * Set envelope |
|
151 * |
|
152 * @param string $envelopeType |
|
153 * @return Zend_Json_Server_Smd |
|
154 */ |
|
155 public function setEnvelope($envelopeType) |
|
156 { |
|
157 if (!in_array($envelopeType, $this->_envelopeTypes)) { |
|
158 require_once 'Zend/Json/Server/Exception.php'; |
|
159 throw new Zend_Json_Server_Exception(sprintf('Invalid envelope type "%s"', $envelopeType)); |
|
160 } |
|
161 $this->_envelope = $envelopeType; |
|
162 return $this; |
|
163 } |
|
164 |
|
165 /** |
|
166 * Retrieve envelope |
|
167 * |
|
168 * @return string |
|
169 */ |
|
170 public function getEnvelope() |
|
171 { |
|
172 return $this->_envelope; |
|
173 } |
|
174 |
|
175 // Content-Type of response; default to application/json |
|
176 /** |
|
177 * Set content type |
|
178 * |
|
179 * @param string $type |
|
180 * @return Zend_Json_Server_Smd |
|
181 */ |
|
182 public function setContentType($type) |
|
183 { |
|
184 if (!preg_match($this->_contentTypeRegex, $type)) { |
|
185 require_once 'Zend/Json/Server/Exception.php'; |
|
186 throw new Zend_Json_Server_Exception(sprintf('Invalid content type "%s" specified', $type)); |
|
187 } |
|
188 $this->_contentType = $type; |
|
189 return $this; |
|
190 } |
|
191 |
|
192 /** |
|
193 * Retrieve content type |
|
194 * |
|
195 * @return string |
|
196 */ |
|
197 public function getContentType() |
|
198 { |
|
199 return $this->_contentType; |
|
200 } |
|
201 |
|
202 /** |
|
203 * Set service target |
|
204 * |
|
205 * @param string $target |
|
206 * @return Zend_Json_Server_Smd |
|
207 */ |
|
208 public function setTarget($target) |
|
209 { |
|
210 $this->_target = (string) $target; |
|
211 return $this; |
|
212 } |
|
213 |
|
214 /** |
|
215 * Retrieve service target |
|
216 * |
|
217 * @return string |
|
218 */ |
|
219 public function getTarget() |
|
220 { |
|
221 return $this->_target; |
|
222 } |
|
223 |
|
224 /** |
|
225 * Set service ID |
|
226 * |
|
227 * @param string $Id |
|
228 * @return Zend_Json_Server_Smd |
|
229 */ |
|
230 public function setId($id) |
|
231 { |
|
232 $this->_id = (string) $id; |
|
233 return $this->_id; |
|
234 } |
|
235 |
|
236 /** |
|
237 * Get service id |
|
238 * |
|
239 * @return string |
|
240 */ |
|
241 public function getId() |
|
242 { |
|
243 return $this->_id; |
|
244 } |
|
245 |
|
246 /** |
|
247 * Set service description |
|
248 * |
|
249 * @param string $description |
|
250 * @return Zend_Json_Server_Smd |
|
251 */ |
|
252 public function setDescription($description) |
|
253 { |
|
254 $this->_description = (string) $description; |
|
255 return $this->_description; |
|
256 } |
|
257 |
|
258 /** |
|
259 * Get service description |
|
260 * |
|
261 * @return string |
|
262 */ |
|
263 public function getDescription() |
|
264 { |
|
265 return $this->_description; |
|
266 } |
|
267 |
|
268 /** |
|
269 * Indicate whether or not to generate Dojo-compatible SMD |
|
270 * |
|
271 * @param bool $flag |
|
272 * @return Zend_Json_Server_Smd |
|
273 */ |
|
274 public function setDojoCompatible($flag) |
|
275 { |
|
276 $this->_dojoCompatible = (bool) $flag; |
|
277 return $this; |
|
278 } |
|
279 |
|
280 /** |
|
281 * Is this a Dojo compatible SMD? |
|
282 * |
|
283 * @return bool |
|
284 */ |
|
285 public function isDojoCompatible() |
|
286 { |
|
287 return $this->_dojoCompatible; |
|
288 } |
|
289 |
|
290 /** |
|
291 * Add Service |
|
292 * |
|
293 * @param Zend_Json_Server_Smd_Service|array $service |
|
294 * @return void |
|
295 */ |
|
296 public function addService($service) |
|
297 { |
|
298 require_once 'Zend/Json/Server/Smd/Service.php'; |
|
299 |
|
300 if ($service instanceof Zend_Json_Server_Smd_Service) { |
|
301 $name = $service->getName(); |
|
302 } elseif (is_array($service)) { |
|
303 $service = new Zend_Json_Server_Smd_Service($service); |
|
304 $name = $service->getName(); |
|
305 } else { |
|
306 require_once 'Zend/Json/Server/Exception.php'; |
|
307 throw new Zend_Json_Server_Exception('Invalid service passed to addService()'); |
|
308 } |
|
309 |
|
310 if (array_key_exists($name, $this->_services)) { |
|
311 require_once 'Zend/Json/Server/Exception.php'; |
|
312 throw new Zend_Json_Server_Exception('Attempt to register a service already registered detected'); |
|
313 } |
|
314 $this->_services[$name] = $service; |
|
315 return $this; |
|
316 } |
|
317 |
|
318 /** |
|
319 * Add many services |
|
320 * |
|
321 * @param array $services |
|
322 * @return Zend_Json_Server_Smd |
|
323 */ |
|
324 public function addServices(array $services) |
|
325 { |
|
326 foreach ($services as $service) { |
|
327 $this->addService($service); |
|
328 } |
|
329 return $this; |
|
330 } |
|
331 |
|
332 /** |
|
333 * Overwrite existing services with new ones |
|
334 * |
|
335 * @param array $services |
|
336 * @return Zend_Json_Server_Smd |
|
337 */ |
|
338 public function setServices(array $services) |
|
339 { |
|
340 $this->_services = array(); |
|
341 return $this->addServices($services); |
|
342 } |
|
343 |
|
344 /** |
|
345 * Get service object |
|
346 * |
|
347 * @param string $name |
|
348 * @return false|Zend_Json_Server_Smd_Service |
|
349 */ |
|
350 public function getService($name) |
|
351 { |
|
352 if (array_key_exists($name, $this->_services)) { |
|
353 return $this->_services[$name]; |
|
354 } |
|
355 return false; |
|
356 } |
|
357 |
|
358 /** |
|
359 * Return services |
|
360 * |
|
361 * @return array |
|
362 */ |
|
363 public function getServices() |
|
364 { |
|
365 return $this->_services; |
|
366 } |
|
367 |
|
368 /** |
|
369 * Remove service |
|
370 * |
|
371 * @param string $name |
|
372 * @return boolean |
|
373 */ |
|
374 public function removeService($name) |
|
375 { |
|
376 if (array_key_exists($name, $this->_services)) { |
|
377 unset($this->_services[$name]); |
|
378 return true; |
|
379 } |
|
380 return false; |
|
381 } |
|
382 |
|
383 /** |
|
384 * Cast to array |
|
385 * |
|
386 * @return array |
|
387 */ |
|
388 public function toArray() |
|
389 { |
|
390 if ($this->isDojoCompatible()) { |
|
391 return $this->toDojoArray(); |
|
392 } |
|
393 |
|
394 $transport = $this->getTransport(); |
|
395 $envelope = $this->getEnvelope(); |
|
396 $contentType = $this->getContentType(); |
|
397 $SMDVersion = self::SMD_VERSION; |
|
398 $service = compact('transport', 'envelope', 'contentType', 'SMDVersion'); |
|
399 |
|
400 if (null !== ($target = $this->getTarget())) { |
|
401 $service['target'] = $target; |
|
402 } |
|
403 if (null !== ($id = $this->getId())) { |
|
404 $service['id'] = $id; |
|
405 } |
|
406 |
|
407 $services = $this->getServices(); |
|
408 if (!empty($services)) { |
|
409 $service['services'] = array(); |
|
410 foreach ($services as $name => $svc) { |
|
411 $svc->setEnvelope($envelope); |
|
412 $service['services'][$name] = $svc->toArray(); |
|
413 } |
|
414 $service['methods'] = $service['services']; |
|
415 } |
|
416 |
|
417 return $service; |
|
418 } |
|
419 |
|
420 /** |
|
421 * Export to DOJO-compatible SMD array |
|
422 * |
|
423 * @return array |
|
424 */ |
|
425 public function toDojoArray() |
|
426 { |
|
427 $SMDVersion = '.1'; |
|
428 $serviceType = 'JSON-RPC'; |
|
429 $service = compact('SMDVersion', 'serviceType'); |
|
430 |
|
431 $target = $this->getTarget(); |
|
432 |
|
433 $services = $this->getServices(); |
|
434 if (!empty($services)) { |
|
435 $service['methods'] = array(); |
|
436 foreach ($services as $name => $svc) { |
|
437 $method = array( |
|
438 'name' => $name, |
|
439 'serviceURL' => $target, |
|
440 ); |
|
441 $params = array(); |
|
442 foreach ($svc->getParams() as $param) { |
|
443 $paramName = array_key_exists('name', $param) ? $param['name'] : $param['type']; |
|
444 $params[] = array( |
|
445 'name' => $paramName, |
|
446 'type' => $param['type'], |
|
447 ); |
|
448 } |
|
449 if (!empty($params)) { |
|
450 $method['parameters'] = $params; |
|
451 } |
|
452 $service['methods'][] = $method; |
|
453 } |
|
454 } |
|
455 |
|
456 return $service; |
|
457 } |
|
458 |
|
459 /** |
|
460 * Cast to JSON |
|
461 * |
|
462 * @return string |
|
463 */ |
|
464 public function toJson() |
|
465 { |
|
466 require_once 'Zend/Json.php'; |
|
467 return Zend_Json::encode($this->toArray()); |
|
468 } |
|
469 |
|
470 /** |
|
471 * Cast to string (JSON) |
|
472 * |
|
473 * @return string |
|
474 */ |
|
475 public function __toString() |
|
476 { |
|
477 return $this->toJson(); |
|
478 } |
|
479 } |
|
480 |