*prechod na novsiu verziu ZF
[sport-group.git] / library / Zend / XmlRpc / Server.php
blobe4910411e427a9a399ea9ff22925d00d8a10f91c
1 <?php
2 /**
3 * Zend Framework
5 * LICENSE
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.
15 * @category Zend
16 * @package Zend_XmlRpc
17 * @subpackage Server
18 * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
19 * @license http://framework.zend.com/license/new-bsd New BSD License
20 * @version $Id: Server.php 17786 2009-08-23 22:26:33Z lars $
23 /**
24 * Extends Zend_Server_Abstract
26 require_once 'Zend/Server/Abstract.php';
28 /**
29 * XMLRPC Request
31 require_once 'Zend/XmlRpc/Request.php';
33 /**
34 * XMLRPC Response
36 require_once 'Zend/XmlRpc/Response.php';
38 /**
39 * XMLRPC HTTP Response
41 require_once 'Zend/XmlRpc/Response/Http.php';
43 /**
44 * XMLRPC server fault class
46 require_once 'Zend/XmlRpc/Server/Fault.php';
48 /**
49 * XMLRPC server system methods class
51 require_once 'Zend/XmlRpc/Server/System.php';
53 /**
54 * Convert PHP to and from xmlrpc native types
56 require_once 'Zend/XmlRpc/Value.php';
58 /**
59 * Reflection API for function/method introspection
61 require_once 'Zend/Server/Reflection.php';
63 /**
64 * Zend_Server_Reflection_Function_Abstract
66 require_once 'Zend/Server/Reflection/Function/Abstract.php';
68 /**
69 * Specifically grab the Zend_Server_Reflection_Method for manually setting up
70 * system.* methods and handling callbacks in {@link loadFunctions()}.
72 require_once 'Zend/Server/Reflection/Method.php';
74 /**
75 * An XML-RPC server implementation
77 * Example:
78 * <code>
79 * require_once 'Zend/XmlRpc/Server.php';
80 * require_once 'Zend/XmlRpc/Server/Cache.php';
81 * require_once 'Zend/XmlRpc/Server/Fault.php';
82 * require_once 'My/Exception.php';
83 * require_once 'My/Fault/Observer.php';
85 * // Instantiate server
86 * $server = new Zend_XmlRpc_Server();
88 * // Allow some exceptions to report as fault responses:
89 * Zend_XmlRpc_Server_Fault::attachFaultException('My_Exception');
90 * Zend_XmlRpc_Server_Fault::attachObserver('My_Fault_Observer');
92 * // Get or build dispatch table:
93 * if (!Zend_XmlRpc_Server_Cache::get($filename, $server)) {
94 * require_once 'Some/Service/Class.php';
95 * require_once 'Another/Service/Class.php';
97 * // Attach Some_Service_Class in 'some' namespace
98 * $server->setClass('Some_Service_Class', 'some');
100 * // Attach Another_Service_Class in 'another' namespace
101 * $server->setClass('Another_Service_Class', 'another');
103 * // Create dispatch table cache file
104 * Zend_XmlRpc_Server_Cache::save($filename, $server);
107 * $response = $server->handle();
108 * echo $response;
109 * </code>
111 * @category Zend
112 * @package Zend_XmlRpc
113 * @subpackage Server
114 * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
115 * @license http://framework.zend.com/license/new-bsd New BSD License
117 class Zend_XmlRpc_Server extends Zend_Server_Abstract
120 * Character encoding
121 * @var string
123 protected $_encoding = 'UTF-8';
126 * Request processed
127 * @var null|Zend_XmlRpc_Request
129 protected $_request = null;
132 * Class to use for responses; defaults to {@link Zend_XmlRpc_Response_Http}
133 * @var string
135 protected $_responseClass = 'Zend_XmlRpc_Response_Http';
138 * Dispatch table of name => method pairs
139 * @var Zend_Server_Definition
141 protected $_table;
144 * PHP types => XML-RPC types
145 * @var array
147 protected $_typeMap = array(
148 'i4' => 'i4',
149 'int' => 'int',
150 'integer' => 'int',
151 'double' => 'double',
152 'float' => 'double',
153 'real' => 'double',
154 'boolean' => 'boolean',
155 'bool' => 'boolean',
156 'true' => 'boolean',
157 'false' => 'boolean',
158 'string' => 'string',
159 'str' => 'string',
160 'base64' => 'base64',
161 'dateTime.iso8601' => 'dateTime.iso8601',
162 'date' => 'dateTime.iso8601',
163 'time' => 'dateTime.iso8601',
164 'time' => 'dateTime.iso8601',
165 'array' => 'array',
166 'struct' => 'struct',
167 'null' => 'nil',
168 'nil' => 'nil',
169 'void' => 'void',
170 'mixed' => 'struct'
174 * Send arguments to all methods or just constructor?
176 * @var bool
178 protected $_sendArgumentsToAllMethods = true;
181 * Constructor
183 * Creates system.* methods.
185 * @return void
187 public function __construct()
189 $this->_table = new Zend_Server_Definition();
190 $this->_registerSystemMethods();
194 * Proxy calls to system object
196 * @param string $method
197 * @param array $params
198 * @return mixed
199 * @throws Zend_XmlRpc_Server_Exception
201 public function __call($method, $params)
203 $system = $this->getSystem();
204 if (!method_exists($system, $method)) {
205 require_once 'Zend/XmlRpc/Server/Exception.php';
206 throw new Zend_XmlRpc_Server_Exception('Unknown instance method called on server: ' . $method);
208 return call_user_func_array(array($system, $method), $params);
212 * Attach a callback as an XMLRPC method
214 * Attaches a callback as an XMLRPC method, prefixing the XMLRPC method name
215 * with $namespace, if provided. Reflection is done on the callback's
216 * docblock to create the methodHelp for the XMLRPC method.
218 * Additional arguments to pass to the function at dispatch may be passed;
219 * any arguments following the namespace will be aggregated and passed at
220 * dispatch time.
222 * @param string|array $function Valid callback
223 * @param string $namespace Optional namespace prefix
224 * @return void
225 * @throws Zend_XmlRpc_Server_Exception
227 public function addFunction($function, $namespace = '')
229 if (!is_string($function) && !is_array($function)) {
230 require_once 'Zend/XmlRpc/Server/Exception.php';
231 throw new Zend_XmlRpc_Server_Exception('Unable to attach function; invalid', 611);
234 $argv = null;
235 if (2 < func_num_args()) {
236 $argv = func_get_args();
237 $argv = array_slice($argv, 2);
240 $function = (array) $function;
241 foreach ($function as $func) {
242 if (!is_string($func) || !function_exists($func)) {
243 require_once 'Zend/XmlRpc/Server/Exception.php';
244 throw new Zend_XmlRpc_Server_Exception('Unable to attach function; invalid', 611);
246 $reflection = Zend_Server_Reflection::reflectFunction($func, $argv, $namespace);
247 $this->_buildSignature($reflection);
252 * Attach class methods as XMLRPC method handlers
254 * $class may be either a class name or an object. Reflection is done on the
255 * class or object to determine the available public methods, and each is
256 * attached to the server as an available method; if a $namespace has been
257 * provided, that namespace is used to prefix the XMLRPC method names.
259 * Any additional arguments beyond $namespace will be passed to a method at
260 * invocation.
262 * @param string|object $class
263 * @param string $namespace Optional
264 * @param mixed $argv Optional arguments to pass to methods
265 * @return void
266 * @throws Zend_XmlRpc_Server_Exception on invalid input
268 public function setClass($class, $namespace = '', $argv = null)
270 if (is_string($class) && !class_exists($class)) {
271 require_once 'Zend/XmlRpc/Server/Exception.php';
272 throw new Zend_XmlRpc_Server_Exception('Invalid method class', 610);
275 $argv = null;
276 if (2 < func_num_args()) {
277 $argv = func_get_args();
278 $argv = array_slice($argv, 2);
281 $dispatchable = Zend_Server_Reflection::reflectClass($class, $argv, $namespace);
282 foreach ($dispatchable->getMethods() as $reflection) {
283 $this->_buildSignature($reflection, $class);
288 * Raise an xmlrpc server fault
290 * @param string|Exception $fault
291 * @param int $code
292 * @return Zend_XmlRpc_Server_Fault
294 public function fault($fault = null, $code = 404)
296 if (!$fault instanceof Exception) {
297 $fault = (string) $fault;
298 if (empty($fault)) {
299 $fault = 'Unknown Error';
301 require_once 'Zend/XmlRpc/Server/Exception.php';
302 $fault = new Zend_XmlRpc_Server_Exception($fault, $code);
305 return Zend_XmlRpc_Server_Fault::getInstance($fault);
309 * Handle an xmlrpc call
311 * @param Zend_XmlRpc_Request $request Optional
312 * @return Zend_XmlRpc_Response|Zend_XmlRpc_Fault
314 public function handle($request = false)
316 // Get request
317 if ((!$request || !$request instanceof Zend_XmlRpc_Request)
318 && (null === ($request = $this->getRequest()))
320 require_once 'Zend/XmlRpc/Request/Http.php';
321 $request = new Zend_XmlRpc_Request_Http();
322 $request->setEncoding($this->getEncoding());
325 $this->setRequest($request);
327 if ($request->isFault()) {
328 $response = $request->getFault();
329 } else {
330 try {
331 $response = $this->_handle($request);
332 } catch (Exception $e) {
333 $response = $this->fault($e);
337 // Set output encoding
338 $response->setEncoding($this->getEncoding());
340 return $response;
344 * Load methods as returned from {@link getFunctions}
346 * Typically, you will not use this method; it will be called using the
347 * results pulled from {@link Zend_XmlRpc_Server_Cache::get()}.
349 * @param array|Zend_Server_Definition $definition
350 * @return void
351 * @throws Zend_XmlRpc_Server_Exception on invalid input
353 public function loadFunctions($definition)
355 if (!is_array($definition) && (!$definition instanceof Zend_Server_Definition)) {
356 if (is_object($definition)) {
357 $type = get_class($definition);
358 } else {
359 $type = gettype($definition);
361 require_once 'Zend/XmlRpc/Server/Exception.php';
362 throw new Zend_XmlRpc_Server_Exception('Unable to load server definition; must be an array or Zend_Server_Definition, received ' . $type, 612);
365 $this->_table->clearMethods();
366 $this->_registerSystemMethods();
368 if ($definition instanceof Zend_Server_Definition) {
369 $definition = $definition->getMethods();
372 foreach ($definition as $key => $method) {
373 if ('system.' == substr($key, 0, 7)) {
374 continue;
376 $this->_table->addMethod($method, $key);
381 * Set encoding
383 * @param string $encoding
384 * @return Zend_XmlRpc_Server
386 public function setEncoding($encoding)
388 $this->_encoding = $encoding;
389 return $this;
393 * Retrieve current encoding
395 * @return string
397 public function getEncoding()
399 return $this->_encoding;
403 * Do nothing; persistence is handled via {@link Zend_XmlRpc_Server_Cache}
405 * @param mixed $mode
406 * @return void
408 public function setPersistence($mode)
413 * Set the request object
415 * @param string|Zend_XmlRpc_Request $request
416 * @return Zend_XmlRpc_Server
417 * @throws Zend_XmlRpc_Server_Exception on invalid request class or object
419 public function setRequest($request)
421 if (is_string($request) && class_exists($request)) {
422 $request = new $request();
423 if (!$request instanceof Zend_XmlRpc_Request) {
424 require_once 'Zend/XmlRpc/Server/Exception.php';
425 throw new Zend_XmlRpc_Server_Exception('Invalid request class');
427 $request->setEncoding($this->getEncoding());
428 } elseif (!$request instanceof Zend_XmlRpc_Request) {
429 require_once 'Zend/XmlRpc/Server/Exception.php';
430 throw new Zend_XmlRpc_Server_Exception('Invalid request object');
433 $this->_request = $request;
434 return $this;
438 * Return currently registered request object
440 * @return null|Zend_XmlRpc_Request
442 public function getRequest()
444 return $this->_request;
448 * Set the class to use for the response
450 * @param string $class
451 * @return boolean True if class was set, false if not
453 public function setResponseClass($class)
455 if (!class_exists($class) or
456 ($c = new ReflectionClass($class) and !$c->isSubclassOf('Zend_XmlRpc_Response'))) {
458 require_once 'Zend/XmlRpc/Server/Exception.php';
459 throw new Zend_XmlRpc_Server_Exception('Invalid response class');
461 $this->_responseClass = $class;
462 return true;
466 * Retrieve current response class
468 * @return string
470 public function getResponseClass()
472 return $this->_responseClass;
476 * Retrieve dispatch table
478 * @return array
480 public function getDispatchTable()
482 return $this->_table;
486 * Returns a list of registered methods
488 * Returns an array of dispatchables (Zend_Server_Reflection_Function,
489 * _Method, and _Class items).
491 * @return array
493 public function getFunctions()
495 return $this->_table->toArray();
499 * Retrieve system object
501 * @return Zend_XmlRpc_Server_System
503 public function getSystem()
505 return $this->_system;
509 * Send arguments to all methods?
511 * If setClass() is used to add classes to the server, this flag defined
512 * how to handle arguments. If set to true, all methods including constructor
513 * will receive the arguments. If set to false, only constructor will receive the
514 * arguments
516 public function sendArgumentsToAllMethods($flag = null)
518 if ($flag === null) {
519 return $this->_sendArgumentsToAllMethods;
522 $this->_sendArgumentsToAllMethods = (bool)$flag;
523 return $this;
527 * Map PHP type to XML-RPC type
529 * @param string $type
530 * @return string
532 protected function _fixType($type)
534 if (isset($this->_typeMap[$type])) {
535 return $this->_typeMap[$type];
537 return 'void';
541 * Handle an xmlrpc call (actual work)
543 * @param Zend_XmlRpc_Request $request
544 * @return Zend_XmlRpc_Response
545 * @throws Zend_XmlRpcServer_Exception|Exception
546 * Zend_XmlRpcServer_Exceptions are thrown for internal errors; otherwise,
547 * any other exception may be thrown by the callback
549 protected function _handle(Zend_XmlRpc_Request $request)
551 $method = $request->getMethod();
553 // Check for valid method
554 if (!$this->_table->hasMethod($method)) {
555 require_once 'Zend/XmlRpc/Server/Exception.php';
556 throw new Zend_XmlRpc_Server_Exception('Method "' . $method . '" does not exist', 620);
559 $info = $this->_table->getMethod($method);
560 $params = $request->getParams();
561 $argv = $info->getInvokeArguments();
562 if (0 < count($argv) and $this->sendArgumentsToAllMethods()) {
563 $params = array_merge($params, $argv);
566 // Check calling parameters against signatures
567 $matched = false;
568 $sigCalled = $request->getTypes();
570 $sigLength = count($sigCalled);
571 $paramsLen = count($params);
572 if ($sigLength < $paramsLen) {
573 for ($i = $sigLength; $i < $paramsLen; ++$i) {
574 $xmlRpcValue = Zend_XmlRpc_Value::getXmlRpcValue($params[$i]);
575 $sigCalled[] = $xmlRpcValue->getType();
579 $signatures = $info->getPrototypes();
580 foreach ($signatures as $signature) {
581 $sigParams = $signature->getParameters();
582 if ($sigCalled === $sigParams) {
583 $matched = true;
584 break;
587 if (!$matched) {
588 require_once 'Zend/XmlRpc/Server/Exception.php';
589 throw new Zend_XmlRpc_Server_Exception('Calling parameters do not match signature', 623);
592 $return = $this->_dispatch($info, $params);
593 $responseClass = $this->getResponseClass();
594 return new $responseClass($return);
598 * Register system methods with the server
600 * @return void
602 protected function _registerSystemMethods()
604 $system = new Zend_XmlRpc_Server_System($this);
605 $this->_system = $system;
606 $this->setClass($system, 'system');