00001 <?php 00024 require_once 'Zend/Json/Server/Smd.php'; 00025 00035 class Zend_Json_Server_Smd_Service 00036 { 00041 protected $_envelope = Zend_Json_Server_Smd::ENV_JSONRPC_1; 00042 protected $_name; 00043 protected $_return; 00044 protected $_target; 00045 protected $_transport = 'POST'; 00052 protected $_envelopeTypes = array( 00053 Zend_Json_Server_Smd::ENV_JSONRPC_1, 00054 Zend_Json_Server_Smd::ENV_JSONRPC_2, 00055 ); 00056 00061 protected $_nameRegex = '/^[a-z][a-z0-9._]+$/i'; 00062 00067 protected $_paramOptionTypes = array( 00068 'name' => 'is_string', 00069 'optional' => 'is_bool', 00070 'default' => null, 00071 'description' => 'is_string', 00072 ); 00073 00078 protected $_params = array(); 00079 00084 protected $_paramMap = array( 00085 'any' => 'any', 00086 'arr' => 'array', 00087 'array' => 'array', 00088 'assoc' => 'object', 00089 'bool' => 'boolean', 00090 'boolean' => 'boolean', 00091 'dbl' => 'float', 00092 'double' => 'float', 00093 'false' => 'boolean', 00094 'float' => 'float', 00095 'hash' => 'object', 00096 'integer' => 'integer', 00097 'int' => 'integer', 00098 'mixed' => 'any', 00099 'nil' => 'null', 00100 'null' => 'null', 00101 'object' => 'object', 00102 'string' => 'string', 00103 'str' => 'string', 00104 'struct' => 'object', 00105 'true' => 'boolean', 00106 'void' => 'null', 00107 ); 00108 00113 protected $_transportTypes = array( 00114 'POST', 00115 ); 00116 00124 public function __construct($spec) 00125 { 00126 if (is_string($spec)) { 00127 $this->setName($spec); 00128 } elseif (is_array($spec)) { 00129 $this->setOptions($spec); 00130 } 00131 00132 if (null == $this->getName()) { 00133 require_once 'Zend/Json/Server/Exception.php'; 00134 throw new Zend_Json_Server_Exception('SMD service description requires a name; none provided'); 00135 } 00136 } 00137 00144 public function setOptions(array $options) 00145 { 00146 $methods = get_class_methods($this); 00147 foreach ($options as $key => $value) { 00148 if ('options' == strtolower($key)) { 00149 continue; 00150 } 00151 $method = 'set' . ucfirst($key); 00152 if (in_array($method, $methods)) { 00153 $this->$method($value); 00154 } 00155 } 00156 return $this; 00157 } 00158 00166 public function setName($name) 00167 { 00168 $name = (string) $name; 00169 if (!preg_match($this->_nameRegex, $name)) { 00170 require_once 'Zend/Json/Server/Exception.php'; 00171 throw new Zend_Json_Server_Exception(sprintf('Invalid name "%s" provided for service; must follow PHP method naming conventions', $name)); 00172 } 00173 $this->_name = $name; 00174 return $this; 00175 } 00176 00182 public function getName() 00183 { 00184 return $this->_name; 00185 } 00186 00195 public function setTransport($transport) 00196 { 00197 if (!in_array($transport, $this->_transportTypes)) { 00198 require_once 'Zend/Json/Server/Exception.php'; 00199 throw new Zend_Json_Server_Exception(sprintf('Invalid transport "%s"; please select one of (%s)', $transport, implode(', ', $this->_transportTypes))); 00200 } 00201 00202 $this->_transport = $transport; 00203 return $this; 00204 } 00205 00211 public function getTransport() 00212 { 00213 return $this->_transport; 00214 } 00215 00222 public function setTarget($target) 00223 { 00224 $this->_target = (string) $target; 00225 return $this; 00226 } 00227 00233 public function getTarget() 00234 { 00235 return $this->_target; 00236 } 00237 00244 public function setEnvelope($envelopeType) 00245 { 00246 if (!in_array($envelopeType, $this->_envelopeTypes)) { 00247 require_once 'Zend/Json/Server/Exception.php'; 00248 throw new Zend_Json_Server_Exception(sprintf('Invalid envelope type "%s"; please specify one of (%s)', $envelopeType, implode(', ', $this->_envelopeTypes))); 00249 } 00250 00251 $this->_envelope = $envelopeType; 00252 return $this; 00253 } 00254 00260 public function getEnvelope() 00261 { 00262 return $this->_envelope; 00263 } 00264 00273 public function addParam($type, array $options = array(), $order = null) 00274 { 00275 if (is_string($type)) { 00276 $type = $this->_validateParamType($type); 00277 } elseif (is_array($type)) { 00278 foreach ($type as $key => $paramType) { 00279 $type[$key] = $this->_validateParamType($paramType); 00280 } 00281 } else { 00282 require_once 'Zend/Json/Server/Exception.php'; 00283 throw new Zend_Json_Server_Exception('Invalid param type provided'); 00284 } 00285 00286 $paramOptions = array( 00287 'type' => $type, 00288 ); 00289 foreach ($options as $key => $value) { 00290 if (in_array($key, array_keys($this->_paramOptionTypes))) { 00291 if (null !== ($callback = $this->_paramOptionTypes[$key])) { 00292 if (!$callback($value)) { 00293 continue; 00294 } 00295 } 00296 $paramOptions[$key] = $value; 00297 } 00298 } 00299 00300 $this->_params[] = array( 00301 'param' => $paramOptions, 00302 'order' => $order, 00303 ); 00304 00305 return $this; 00306 } 00307 00316 public function addParams(array $params) 00317 { 00318 ksort($params); 00319 foreach ($params as $options) { 00320 if (!is_array($options)) { 00321 continue; 00322 } 00323 if (!array_key_exists('type', $options)) { 00324 continue; 00325 } 00326 $type = $options['type']; 00327 $order = (array_key_exists('order', $options)) ? $options['order'] : null; 00328 $this->addParam($type, $options, $order); 00329 } 00330 return $this; 00331 } 00332 00339 public function setParams(array $params) 00340 { 00341 $this->_params = array(); 00342 return $this->addParams($params); 00343 } 00344 00352 public function getParams() 00353 { 00354 $params = array(); 00355 $index = 0; 00356 foreach ($this->_params as $param) { 00357 if (null === $param['order']) { 00358 if (array_search($index, array_keys($params), true)) { 00359 ++$index; 00360 } 00361 $params[$index] = $param['param']; 00362 ++$index; 00363 } else { 00364 $params[$param['order']] = $param['param']; 00365 } 00366 } 00367 ksort($params); 00368 return $params; 00369 } 00370 00377 public function setReturn($type) 00378 { 00379 if (is_string($type)) { 00380 $type = $this->_validateParamType($type, true); 00381 } elseif (is_array($type)) { 00382 foreach ($type as $key => $returnType) { 00383 $type[$key] = $this->_validateParamType($returnType, true); 00384 } 00385 } else { 00386 require_once 'Zend/Json/Server/Exception.php'; 00387 throw new Zend_Json_Server_Exception('Invalid param type provided ("' . gettype($type) .'")'); 00388 } 00389 $this->_return = $type; 00390 return $this; 00391 } 00392 00398 public function getReturn() 00399 { 00400 return $this->_return; 00401 } 00402 00408 public function toArray() 00409 { 00410 $name = $this->getName(); 00411 $envelope = $this->getEnvelope(); 00412 $target = $this->getTarget(); 00413 $transport = $this->getTransport(); 00414 $parameters = $this->getParams(); 00415 $returns = $this->getReturn(); 00416 00417 if (empty($target)) { 00418 return compact('envelope', 'transport', 'parameters', 'returns'); 00419 } 00420 00421 return $paramInfo = compact('envelope', 'target', 'transport', 'parameters', 'returns'); 00422 } 00423 00429 public function toJson() 00430 { 00431 $service = array($this->getName() => $this->toArray()); 00432 00433 require_once 'Zend/Json.php'; 00434 return Zend_Json::encode($service); 00435 } 00436 00442 public function __toString() 00443 { 00444 return $this->toJson(); 00445 } 00446 00454 protected function _validateParamType($type, $isReturn = false) 00455 { 00456 if (!is_string($type)) { 00457 require_once 'Zend/Json/Server/Exception.php'; 00458 throw new Zend_Json_Server_Exception('Invalid param type provided ("' . $type .'")'); 00459 } 00460 00461 if (!array_key_exists($type, $this->_paramMap)) { 00462 $type = 'object'; 00463 } 00464 00465 $paramType = $this->_paramMap[$type]; 00466 if (!$isReturn && ('null' == $paramType)) { 00467 require_once 'Zend/Json/Server/Exception.php'; 00468 throw new Zend_Json_Server_Exception('Invalid param type provided ("' . $type . '")'); 00469 } 00470 00471 return $paramType; 00472 } 00473 }