00001 <?php
00025 require_once 'Zend/Server/Abstract.php';
00026
00033 class Zend_Json_Server extends Zend_Server_Abstract
00034 {
00039 const VERSION_1 = '1.0';
00040 const VERSION_2 = '2.0';
00047 protected $_autoEmitResponse = true;
00048
00052 protected $_overwriteExistingMethods = true;
00053
00058 protected $_request;
00059
00064 protected $_response;
00065
00070 protected $_serviceMap;
00071
00076 protected $_smdMethods;
00077
00081 protected $_table;
00082
00090 public function addFunction($function, $namespace = '')
00091 {
00092 if (!is_string($function) && (!is_array($function) || (2 > count($function)))) {
00093 require_once 'Zend/Json/Server/Exception.php';
00094 throw new Zend_Json_Server_Exception('Unable to attach function; invalid');
00095 }
00096
00097 if (!is_callable($function)) {
00098 require_once 'Zend/Json/Server/Exception.php';
00099 throw new Zend_Json_Server_Exception('Unable to attach function; does not exist');
00100 }
00101
00102 $argv = null;
00103 if (2 < func_num_args()) {
00104 $argv = func_get_args();
00105 $argv = array_slice($argv, 2);
00106 }
00107
00108 require_once 'Zend/Server/Reflection.php';
00109 if (is_string($function)) {
00110 $method = Zend_Server_Reflection::reflectFunction($function, $argv, $namespace);
00111 } else {
00112 $class = array_shift($function);
00113 $action = array_shift($function);
00114 $reflection = Zend_Server_Reflection::reflectClass($class, $argv, $namespace);
00115 $methods = $reflection->getMethods();
00116 $found = false;
00117 foreach ($methods as $method) {
00118 if ($action == $method->getName()) {
00119 $found = true;
00120 break;
00121 }
00122 }
00123 if (!$found) {
00124 $this->fault('Method not found', -32601);
00125 return $this;
00126 }
00127 }
00128
00129 $definition = $this->_buildSignature($method);
00130 $this->_addMethodServiceMap($definition);
00131
00132 return $this;
00133 }
00134
00143 public function setClass($class, $namespace = '', $argv = null)
00144 {
00145 $argv = null;
00146 if (3 < func_num_args()) {
00147 $argv = func_get_args();
00148 $argv = array_slice($argv, 3);
00149 }
00150
00151 require_once 'Zend/Server/Reflection.php';
00152 $reflection = Zend_Server_Reflection::reflectClass($class, $argv, $namespace);
00153
00154 foreach ($reflection->getMethods() as $method) {
00155 $definition = $this->_buildSignature($method, $class);
00156 $this->_addMethodServiceMap($definition);
00157 }
00158 return $this;
00159 }
00160
00168 public function fault($fault = null, $code = 404, $data = null)
00169 {
00170 require_once 'Zend/Json/Server/Error.php';
00171 $error = new Zend_Json_Server_Error($fault, $code, $data);
00172 $this->getResponse()->setError($error);
00173 return $error;
00174 }
00175
00182 public function handle($request = false)
00183 {
00184 if ((false !== $request) && (!$request instanceof Zend_Json_Server_Request)) {
00185 require_once 'Zend/Json/Server/Exception.php';
00186 throw new Zend_Json_Server_Exception('Invalid request type provided; cannot handle');
00187 } elseif ($request) {
00188 $this->setRequest($request);
00189 }
00190
00191
00192 $this->_handle();
00193
00194
00195 $response = $this->_getReadyResponse();
00196
00197
00198 if ($this->autoEmitResponse()) {
00199 echo $response;
00200 return;
00201 }
00202
00203
00204 return $response;
00205 }
00206
00213 public function loadFunctions($definition)
00214 {
00215 if (!is_array($definition) && (!$definition instanceof Zend_Server_Definition)) {
00216 require_once 'Zend/Json/Server/Exception.php';
00217 throw new Zend_Json_Server_Exception('Invalid definition provided to loadFunctions()');
00218 }
00219
00220 foreach ($definition as $key => $method) {
00221 $this->_table->addMethod($method, $key);
00222 $this->_addMethodServiceMap($method);
00223 }
00224 }
00225
00226 public function setPersistence($mode)
00227 {
00228 }
00229
00236 public function setRequest(Zend_Json_Server_Request $request)
00237 {
00238 $this->_request = $request;
00239 return $this;
00240 }
00241
00247 public function getRequest()
00248 {
00249 if (null === ($request = $this->_request)) {
00250 require_once 'Zend/Json/Server/Request/Http.php';
00251 $this->setRequest(new Zend_Json_Server_Request_Http());
00252 }
00253 return $this->_request;
00254 }
00255
00262 public function setResponse(Zend_Json_Server_Response $response)
00263 {
00264 $this->_response = $response;
00265 return $this;
00266 }
00267
00273 public function getResponse()
00274 {
00275 if (null === ($response = $this->_response)) {
00276 require_once 'Zend/Json/Server/Response/Http.php';
00277 $this->setResponse(new Zend_Json_Server_Response_Http());
00278 }
00279 return $this->_response;
00280 }
00281
00288 public function setAutoEmitResponse($flag)
00289 {
00290 $this->_autoEmitResponse = (bool) $flag;
00291 return $this;
00292 }
00293
00299 public function autoEmitResponse()
00300 {
00301 return $this->_autoEmitResponse;
00302 }
00303
00304
00312 public function __call($method, $args)
00313 {
00314 if (preg_match('/^(set|get)/', $method, $matches)) {
00315 if (in_array($method, $this->_getSmdMethods())) {
00316 if ('set' == $matches[1]) {
00317 $value = array_shift($args);
00318 $this->getServiceMap()->$method($value);
00319 return $this;
00320 } else {
00321 return $this->getServiceMap()->$method();
00322 }
00323 }
00324 }
00325 return null;
00326 }
00327
00333 public function getServiceMap()
00334 {
00335 if (null === $this->_serviceMap) {
00336 require_once 'Zend/Json/Server/Smd.php';
00337 $this->_serviceMap = new Zend_Json_Server_Smd();
00338 }
00339 return $this->_serviceMap;
00340 }
00341
00348 protected function _addMethodServiceMap(Zend_Server_Method_Definition $method)
00349 {
00350 $serviceInfo = array(
00351 'name' => $method->getName(),
00352 'return' => $this->_getReturnType($method),
00353 );
00354 $params = $this->_getParams($method);
00355 $serviceInfo['params'] = $params;
00356 $serviceMap = $this->getServiceMap();
00357 if (false !== $serviceMap->getService($serviceInfo['name'])) {
00358 $serviceMap->removeService($serviceInfo['name']);
00359 }
00360 $serviceMap->addService($serviceInfo);
00361 }
00362
00369 protected function _fixType($type)
00370 {
00371 return $type;
00372 }
00373
00381 protected function _getDefaultParams(array $args, array $params)
00382 {
00383 $defaultParams = array_slice($params, count($args));
00384 foreach ($defaultParams as $param) {
00385 $value = null;
00386 if (array_key_exists('default', $param)) {
00387 $value = $param['default'];
00388 }
00389 array_push($args, $value);
00390 }
00391 return $args;
00392 }
00393
00400 protected function _getParams(Zend_Server_Method_Definition $method)
00401 {
00402 $params = array();
00403 foreach ($method->getPrototypes() as $prototype) {
00404 foreach ($prototype->getParameterObjects() as $key => $parameter) {
00405 if (!isset($params[$key])) {
00406 $params[$key] = array(
00407 'type' => $parameter->getType(),
00408 'name' => $parameter->getName(),
00409 'optional' => $parameter->isOptional(),
00410 );
00411 if (null !== ($default = $parameter->getDefaultValue())) {
00412 $params[$key]['default'] = $default;
00413 }
00414 $description = $parameter->getDescription();
00415 if (!empty($description)) {
00416 $params[$key]['description'] = $description;
00417 }
00418 continue;
00419 }
00420 $newType = $parameter->getType();
00421 if (!is_array($params[$key]['type'])) {
00422 if ($params[$key]['type'] == $newType) {
00423 continue;
00424 }
00425 $params[$key]['type'] = (array) $params[$key]['type'];
00426 } elseif (in_array($newType, $params[$key]['type'])) {
00427 continue;
00428 }
00429 array_push($params[$key]['type'], $parameter->getType());
00430 }
00431 }
00432 return $params;
00433 }
00434
00440 protected function _getReadyResponse()
00441 {
00442 $request = $this->getRequest();
00443 $response = $this->getResponse();
00444
00445 $response->setServiceMap($this->getServiceMap());
00446 if (null !== ($id = $request->getId())) {
00447 $response->setId($id);
00448 }
00449 if (null !== ($version = $request->getVersion())) {
00450 $response->setVersion($version);
00451 }
00452
00453 return $response;
00454 }
00455
00462 protected function _getReturnType(Zend_Server_Method_Definition $method)
00463 {
00464 $return = array();
00465 foreach ($method->getPrototypes() as $prototype) {
00466 $return[] = $prototype->getReturnType();
00467 }
00468 if (1 == count($return)) {
00469 return $return[0];
00470 }
00471 return $return;
00472 }
00473
00479 protected function _getSmdMethods()
00480 {
00481 if (null === $this->_smdMethods) {
00482 $this->_smdMethods = array();
00483 require_once 'Zend/Json/Server/Smd.php';
00484 $methods = get_class_methods('Zend_Json_Server_Smd');
00485 foreach ($methods as $key => $method) {
00486 if (!preg_match('/^(set|get)/', $method)) {
00487 continue;
00488 }
00489 if (strstr($method, 'Service')) {
00490 continue;
00491 }
00492 $this->_smdMethods[] = $method;
00493 }
00494 }
00495 return $this->_smdMethods;
00496 }
00497
00503 protected function _handle()
00504 {
00505 $request = $this->getRequest();
00506
00507 if (!$request->isMethodError() && (null === $request->getMethod())) {
00508 return $this->fault('Invalid Request', -32600);
00509 }
00510
00511 if ($request->isMethodError()) {
00512 return $this->fault('Invalid Request', -32600);
00513 }
00514
00515 $method = $request->getMethod();
00516 if (!$this->_table->hasMethod($method)) {
00517 return $this->fault('Method not found', -32601);
00518 }
00519
00520 $params = $request->getParams();
00521 $invocable = $this->_table->getMethod($method);
00522 $serviceMap = $this->getServiceMap();
00523 $service = $serviceMap->getService($method);
00524 $serviceParams = $service->getParams();
00525
00526 if (count($params) < count($serviceParams)) {
00527 $params = $this->_getDefaultParams($params, $serviceParams);
00528 }
00529
00530 try {
00531 $result = $this->_dispatch($invocable, $params);
00532 } catch (Exception $e) {
00533 return $this->fault($e->getMessage(), $e->getCode());
00534 }
00535
00536 $this->getResponse()->setResult($result);
00537 }
00538 }