File indexing completed on 2025-02-23 05:32:28

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category   Zend
0016  * @package    Zend_Json
0017  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0018  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0019  */
0020 
0021 /**
0022  * @see Zend_Json_Server_Smd
0023  */
0024 // require_once 'Zend/Json/Server/Smd.php';
0025 
0026 /**
0027  * Create Service Mapping Description for a method
0028  *
0029  * @package    Zend_Json
0030  * @subpackage Server
0031  * @version    $Id$
0032  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0033  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0034  */
0035 class Zend_Json_Server_Smd_Service
0036 {
0037     /**#@+
0038      * Service metadata
0039      * @var string
0040      */
0041     protected $_envelope  = Zend_Json_Server_Smd::ENV_JSONRPC_1;
0042     protected $_name;
0043     protected $_return;
0044     protected $_target;
0045     protected $_transport = 'POST';
0046     /**#@-*/
0047 
0048     /**
0049      * Allowed envelope types
0050      * @var array
0051      */
0052     protected $_envelopeTypes = array(
0053         Zend_Json_Server_Smd::ENV_JSONRPC_1,
0054         Zend_Json_Server_Smd::ENV_JSONRPC_2,
0055     );
0056 
0057     /**
0058      * Regex for names
0059      * @var string
0060      */
0061     protected $_nameRegex = '/^[a-z][a-z0-9._]+$/i';
0062 
0063     /**
0064      * Parameter option types
0065      * @var array
0066      */
0067     protected $_paramOptionTypes = array(
0068         'name'        => 'is_string',
0069         'optional'    => 'is_bool',
0070         'default'     => null,
0071         'description' => 'is_string',
0072     );
0073 
0074     /**
0075      * Service params
0076      * @var array
0077      */
0078     protected $_params = array();
0079 
0080     /**
0081      * Mapping of parameter types to JSON-RPC types
0082      * @var array
0083      */
0084     protected $_paramMap = array(
0085         'any'     => 'any',
0086         'arr'     => 'array',
0087         'array'   => 'array',
0088         'assoc'   => 'object',
0089         'bool'    => 'boolean',
0090         'boolean' => 'boolean',
0091         'dbl'     => 'float',
0092         'double'  => 'float',
0093         'false'   => 'boolean',
0094         'float'   => 'float',
0095         'hash'    => 'object',
0096         'integer' => 'integer',
0097         'int'     => 'integer',
0098         'mixed'   => 'any',
0099         'nil'     => 'null',
0100         'null'    => 'null',
0101         'object'  => 'object',
0102         'string'  => 'string',
0103         'str'     => 'string',
0104         'struct'  => 'object',
0105         'true'    => 'boolean',
0106         'void'    => 'null',
0107     );
0108 
0109     /**
0110      * Allowed transport types
0111      * @var array
0112      */
0113     protected $_transportTypes = array(
0114         'POST',
0115     );
0116 
0117     /**
0118      * Constructor
0119      *
0120      * @param  string|array $spec
0121      * @return void
0122      * @throws Zend_Json_Server_Exception if no name provided
0123      */
0124     public function __construct($spec)
0125     {
0126         if (is_string($spec)) {
0127             $this->setName($spec);
0128         } elseif (is_array($spec)) {
0129             $this->setOptions($spec);
0130         }
0131 
0132         if (null == $this->getName()) {
0133             // require_once 'Zend/Json/Server/Exception.php';
0134             throw new Zend_Json_Server_Exception('SMD service description requires a name; none provided');
0135         }
0136     }
0137 
0138     /**
0139      * Set object state
0140      *
0141      * @param  array $options
0142      * @return Zend_Json_Server_Smd_Service
0143      */
0144     public function setOptions(array $options)
0145     {
0146         $methods = get_class_methods($this);
0147         foreach ($options as $key => $value) {
0148             if ('options' == strtolower($key)) {
0149                 continue;
0150             }
0151             $method = 'set' . ucfirst($key);
0152             if (in_array($method, $methods)) {
0153                 $this->$method($value);
0154             }
0155         }
0156         return $this;
0157     }
0158 
0159     /**
0160      * Set service name
0161      *
0162      * @param  string $name
0163      * @return Zend_Json_Server_Smd_Service
0164      * @throws Zend_Json_Server_Exception
0165      */
0166     public function setName($name)
0167     {
0168         $name = (string) $name;
0169         if (!preg_match($this->_nameRegex, $name)) {
0170             // require_once 'Zend/Json/Server/Exception.php';
0171             throw new Zend_Json_Server_Exception(sprintf('Invalid name "%s" provided for service; must follow PHP method naming conventions', $name));
0172         }
0173         $this->_name = $name;
0174         return $this;
0175     }
0176 
0177     /**
0178      * Retrieve name
0179      *
0180      * @return string
0181      */
0182     public function getName()
0183     {
0184         return $this->_name;
0185     }
0186 
0187     /**
0188      * Set Transport
0189      *
0190      * Currently limited to POST
0191      *
0192      * @param  string $transport
0193      * @return Zend_Json_Server_Smd_Service
0194      */
0195     public function setTransport($transport)
0196     {
0197         if (!in_array($transport, $this->_transportTypes)) {
0198             // require_once 'Zend/Json/Server/Exception.php';
0199             throw new Zend_Json_Server_Exception(sprintf('Invalid transport "%s"; please select one of (%s)', $transport, implode(', ', $this->_transportTypes)));
0200         }
0201 
0202         $this->_transport = $transport;
0203         return $this;
0204     }
0205 
0206     /**
0207      * Get transport
0208      *
0209      * @return string
0210      */
0211     public function getTransport()
0212     {
0213         return $this->_transport;
0214     }
0215 
0216     /**
0217      * Set service target
0218      *
0219      * @param  string $target
0220      * @return Zend_Json_Server_Smd_Service
0221      */
0222     public function setTarget($target)
0223     {
0224         $this->_target = (string) $target;
0225         return $this;
0226     }
0227 
0228     /**
0229      * Get service target
0230      *
0231      * @return string
0232      */
0233     public function getTarget()
0234     {
0235         return $this->_target;
0236     }
0237 
0238     /**
0239      * Set envelope type
0240      *
0241      * @param  string $envelopeType
0242      * @return Zend_Json_Server_Smd_Service
0243      */
0244     public function setEnvelope($envelopeType)
0245     {
0246         if (!in_array($envelopeType, $this->_envelopeTypes)) {
0247             // require_once 'Zend/Json/Server/Exception.php';
0248             throw new Zend_Json_Server_Exception(sprintf('Invalid envelope type "%s"; please specify one of (%s)', $envelopeType, implode(', ', $this->_envelopeTypes)));
0249         }
0250 
0251         $this->_envelope = $envelopeType;
0252         return $this;
0253     }
0254 
0255     /**
0256      * Get envelope type
0257      *
0258      * @return string
0259      */
0260     public function getEnvelope()
0261     {
0262         return $this->_envelope;
0263     }
0264 
0265     /**
0266      * Add a parameter to the service
0267      *
0268      * @param  string|array $type
0269      * @param  array $options
0270      * @param  int|null $order
0271      * @return Zend_Json_Server_Smd_Service
0272      */
0273     public function addParam($type, array $options = array(), $order = null)
0274     {
0275         if (is_string($type)) {
0276             $type = $this->_validateParamType($type);
0277         } elseif (is_array($type)) {
0278             foreach ($type as $key => $paramType) {
0279                 $type[$key] = $this->_validateParamType($paramType);
0280             }
0281         } else {
0282             // require_once 'Zend/Json/Server/Exception.php';
0283             throw new Zend_Json_Server_Exception('Invalid param type provided');
0284         }
0285 
0286         $paramOptions = array(
0287             'type' => $type,
0288         );
0289         foreach ($options as $key => $value) {
0290             if (in_array($key, array_keys($this->_paramOptionTypes))) {
0291                 if (null !== ($callback = $this->_paramOptionTypes[$key])) {
0292                     if (!$callback($value)) {
0293                         continue;
0294                     }
0295                 }
0296                 $paramOptions[$key] = $value;
0297             }
0298         }
0299 
0300         $this->_params[] = array(
0301             'param' => $paramOptions,
0302             'order' => $order,
0303         );
0304 
0305         return $this;
0306     }
0307 
0308     /**
0309      * Add params
0310      *
0311      * Each param should be an array, and should include the key 'type'.
0312      *
0313      * @param  array $params
0314      * @return Zend_Json_Server_Smd_Service
0315      */
0316     public function addParams(array $params)
0317     {
0318         ksort($params);
0319         foreach ($params as $options) {
0320             if (!is_array($options)) {
0321                 continue;
0322             }
0323             if (!array_key_exists('type', $options)) {
0324                 continue;
0325             }
0326             $type  = $options['type'];
0327             $order = (array_key_exists('order', $options)) ? $options['order'] : null;
0328             $this->addParam($type, $options, $order);
0329         }
0330         return $this;
0331     }
0332 
0333     /**
0334      * Overwrite all parameters
0335      *
0336      * @param  array $params
0337      * @return Zend_Json_Server_Smd_Service
0338      */
0339     public function setParams(array $params)
0340     {
0341         $this->_params = array();
0342         return $this->addParams($params);
0343     }
0344 
0345     /**
0346      * Get all parameters
0347      *
0348      * Returns all params in specified order.
0349      *
0350      * @return array
0351      */
0352     public function getParams()
0353     {
0354         $params = array();
0355         $index  = 0;
0356         foreach ($this->_params as $param) {
0357             if (null === $param['order']) {
0358                 if (array_search($index, array_keys($params), true)) {
0359                     ++$index;
0360                 }
0361                 $params[$index] = $param['param'];
0362                 ++$index;
0363             } else {
0364                 $params[$param['order']] = $param['param'];
0365             }
0366         }
0367         ksort($params);
0368         return $params;
0369     }
0370 
0371     /**
0372      * Set return type
0373      *
0374      * @param  string|array $type
0375      * @return Zend_Json_Server_Smd_Service
0376      */
0377     public function setReturn($type)
0378     {
0379         if (is_string($type)) {
0380             $type = $this->_validateParamType($type, true);
0381         } elseif (is_array($type)) {
0382             foreach ($type as $key => $returnType) {
0383                 $type[$key] = $this->_validateParamType($returnType, true);
0384             }
0385         } else {
0386             // require_once 'Zend/Json/Server/Exception.php';
0387             throw new Zend_Json_Server_Exception('Invalid param type provided ("' . gettype($type) .'")');
0388         }
0389         $this->_return = $type;
0390         return $this;
0391     }
0392 
0393     /**
0394      * Get return type
0395      *
0396      * @return string|array
0397      */
0398     public function getReturn()
0399     {
0400         return $this->_return;
0401     }
0402 
0403     /**
0404      * Cast service description to array
0405      *
0406      * @return array
0407      */
0408     public function toArray()
0409     {
0410         $name       = $this->getName();
0411         $envelope   = $this->getEnvelope();
0412         $target     = $this->getTarget();
0413         $transport  = $this->getTransport();
0414         $parameters = $this->getParams();
0415         $returns    = $this->getReturn();
0416 
0417         if (empty($target)) {
0418             return compact('envelope', 'transport', 'parameters', 'returns');
0419         }
0420 
0421         return $paramInfo = compact('envelope', 'target', 'transport', 'parameters', 'returns');
0422     }
0423 
0424     /**
0425      * Return JSON encoding of service
0426      *
0427      * @return string
0428      */
0429     public function toJson()
0430     {
0431         $service = array($this->getName() => $this->toArray());
0432 
0433         // require_once 'Zend/Json.php';
0434         return Zend_Json::encode($service);
0435     }
0436 
0437     /**
0438      * Cast to string
0439      *
0440      * @return string
0441      */
0442     public function __toString()
0443     {
0444         return $this->toJson();
0445     }
0446 
0447     /**
0448      * Validate parameter type
0449      *
0450      * @param  string $type
0451      * @return true
0452      * @throws Zend_Json_Server_Exception
0453      */
0454     protected function _validateParamType($type, $isReturn = false)
0455     {
0456         if (!is_string($type)) {
0457             // require_once 'Zend/Json/Server/Exception.php';
0458             throw new Zend_Json_Server_Exception('Invalid param type provided ("' . $type .'")');
0459         }
0460 
0461         if (!array_key_exists($type, $this->_paramMap)) {
0462             $type = 'object';
0463         }
0464 
0465         $paramType = $this->_paramMap[$type];
0466         if (!$isReturn && ('null' == $paramType)) {
0467             // require_once 'Zend/Json/Server/Exception.php';
0468             throw new Zend_Json_Server_Exception('Invalid param type provided ("' . $type . '")');
0469         }
0470 
0471         return $paramType;
0472     }
0473 }