1<?php
2namespace IXR\Server;
3
4use IXR\Message\Error;
5
6/**
7 * Extension of the {@link Server} class to easily wrap objects.
8 *
9 * Class is designed to extend the existing XML-RPC server to allow the
10 * presentation of methods from a variety of different objects via an
11 * XML-RPC server.
12 * It is intended to assist in organization of your XML-RPC methods by allowing
13 * you to "write once" in your existing model classes and present them.
14 *
15 * @author Jason Stirk <jstirk@gmm.com.au>
16 * @version 1.0.1 19Apr2005 17:40 +0800
17 * @copyright Copyright (c) 2005 Jason Stirk
18 * @package IXR
19 */
20class ClassServer extends Server
21{
22
23    private $_objects;
24    private $_delim;
25
26    public function __construct($delim = '.', $wait = false)
27    {
28        parent::__construct([], false, $wait);
29        $this->_delim = $delim;
30        $this->_objects = [];
31    }
32
33    public function addMethod($rpcName, $functionName)
34    {
35        $this->callbacks[$rpcName] = $functionName;
36    }
37
38    public function registerObject($object, $methods, $prefix = null)
39    {
40        if (is_null($prefix)) {
41            $prefix = get_class($object);
42        }
43        $this->_objects[$prefix] = $object;
44
45        // Add to our callbacks array
46        foreach ($methods as $method) {
47            if (is_array($method)) {
48                $targetMethod = $method[0];
49                $method = $method[1];
50            } else {
51                $targetMethod = $method;
52            }
53            $this->callbacks[$prefix . $this->_delim . $method] = [$prefix, $targetMethod];
54        }
55    }
56
57    public function call($methodname, $args)
58    {
59        if (!$this->hasMethod($methodname)) {
60            return new Error(-32601, 'server error. requested method ' . $methodname . ' does not exist.');
61        }
62        $method = $this->callbacks[$methodname];
63
64        // Perform the callback and send the response
65        if (count($args) == 1) {
66            // If only one paramater just send that instead of the whole array
67            $args = $args[0];
68        }
69
70        // See if this method comes from one of our objects or maybe self
71        if (is_array($method) || (substr($method, 0, 5) == 'this:')) {
72            if (is_array($method)) {
73                $object = $this->_objects[$method[0]];
74                $method = $method[1];
75            } else {
76                $object = $this;
77                $method = substr($method, 5);
78            }
79
80            // It's a class method - check it exists
81            if (!method_exists($object, $method)) {
82                return new Error(-32601, 'server error. requested class method "' . $method . '" does not exist.');
83            }
84
85            // Call the method
86            $result = $object->$method($args);
87        } else {
88            // It's a function - does it exist?
89            if (!function_exists($method)) {
90                return new Error(-32601, 'server error. requested function "' . $method . '" does not exist.');
91            }
92
93            // Call the function
94            $result = $method($args);
95        }
96        return $result;
97    }
98}
99