xref: /dokuwiki/vendor/kissifrot/php-ixr/src/Server/IntrospectionServer.php (revision 7f8f24562b596c56d79e46eba9f82780df5725cb)
1*7f8f2456SAndreas Gohr<?php
2*7f8f2456SAndreas Gohrnamespace IXR\Server;
3*7f8f2456SAndreas Gohr
4*7f8f2456SAndreas Gohruse IXR\DataType\Base64;
5*7f8f2456SAndreas Gohruse IXR\DataType\Date;
6*7f8f2456SAndreas Gohruse IXR\Message\Error;
7*7f8f2456SAndreas Gohr
8*7f8f2456SAndreas Gohr/**
9*7f8f2456SAndreas Gohr * IXR_IntrospectionServer
10*7f8f2456SAndreas Gohr *
11*7f8f2456SAndreas Gohr * @package IXR
12*7f8f2456SAndreas Gohr * @since 1.5.0
13*7f8f2456SAndreas Gohr */
14*7f8f2456SAndreas Gohrclass IntrospectionServer extends Server
15*7f8f2456SAndreas Gohr{
16*7f8f2456SAndreas Gohr
17*7f8f2456SAndreas Gohr    private $signatures;
18*7f8f2456SAndreas Gohr    private $help;
19*7f8f2456SAndreas Gohr
20*7f8f2456SAndreas Gohr    public function __construct()
21*7f8f2456SAndreas Gohr    {
22*7f8f2456SAndreas Gohr        $this->setCallbacks();
23*7f8f2456SAndreas Gohr        $this->setCapabilities();
24*7f8f2456SAndreas Gohr        $this->capabilities['introspection'] = [
25*7f8f2456SAndreas Gohr            'specUrl' => 'http://xmlrpc.usefulinc.com/doc/reserved.html',
26*7f8f2456SAndreas Gohr            'specVersion' => 1
27*7f8f2456SAndreas Gohr        ];
28*7f8f2456SAndreas Gohr        $this->addCallback(
29*7f8f2456SAndreas Gohr            'system.methodSignature',
30*7f8f2456SAndreas Gohr            'this:methodSignature',
31*7f8f2456SAndreas Gohr            ['array', 'string'],
32*7f8f2456SAndreas Gohr            'Returns an array describing the return type and required parameters of a method'
33*7f8f2456SAndreas Gohr        );
34*7f8f2456SAndreas Gohr        $this->addCallback(
35*7f8f2456SAndreas Gohr            'system.getCapabilities',
36*7f8f2456SAndreas Gohr            'this:getCapabilities',
37*7f8f2456SAndreas Gohr            ['struct'],
38*7f8f2456SAndreas Gohr            'Returns a struct describing the XML-RPC specifications supported by this server'
39*7f8f2456SAndreas Gohr        );
40*7f8f2456SAndreas Gohr        $this->addCallback(
41*7f8f2456SAndreas Gohr            'system.listMethods',
42*7f8f2456SAndreas Gohr            'this:listMethods',
43*7f8f2456SAndreas Gohr            ['array'],
44*7f8f2456SAndreas Gohr            'Returns an array of available methods on this server'
45*7f8f2456SAndreas Gohr        );
46*7f8f2456SAndreas Gohr        $this->addCallback(
47*7f8f2456SAndreas Gohr            'system.methodHelp',
48*7f8f2456SAndreas Gohr            'this:methodHelp',
49*7f8f2456SAndreas Gohr            ['string', 'string'],
50*7f8f2456SAndreas Gohr            'Returns a documentation string for the specified method'
51*7f8f2456SAndreas Gohr        );
52*7f8f2456SAndreas Gohr    }
53*7f8f2456SAndreas Gohr
54*7f8f2456SAndreas Gohr    public function addCallback($method, $callback, $args, $help)
55*7f8f2456SAndreas Gohr    {
56*7f8f2456SAndreas Gohr        $this->callbacks[$method] = $callback;
57*7f8f2456SAndreas Gohr        $this->signatures[$method] = $args;
58*7f8f2456SAndreas Gohr        $this->help[$method] = $help;
59*7f8f2456SAndreas Gohr    }
60*7f8f2456SAndreas Gohr
61*7f8f2456SAndreas Gohr    public function call($methodname, $args)
62*7f8f2456SAndreas Gohr    {
63*7f8f2456SAndreas Gohr        // Make sure it's in an array
64*7f8f2456SAndreas Gohr        if ($args && !is_array($args)) {
65*7f8f2456SAndreas Gohr            $args = [$args];
66*7f8f2456SAndreas Gohr        }
67*7f8f2456SAndreas Gohr
68*7f8f2456SAndreas Gohr        // Over-rides default call method, adds signature check
69*7f8f2456SAndreas Gohr        if (!$this->hasMethod($methodname)) {
70*7f8f2456SAndreas Gohr            return new Error(-32601,
71*7f8f2456SAndreas Gohr                'server error. requested method "' . $this->message->methodName . '" not specified.');
72*7f8f2456SAndreas Gohr        }
73*7f8f2456SAndreas Gohr        $method = $this->callbacks[$methodname];
74*7f8f2456SAndreas Gohr        $signature = $this->signatures[$methodname];
75*7f8f2456SAndreas Gohr        array_shift($signature);
76*7f8f2456SAndreas Gohr
77*7f8f2456SAndreas Gohr        // Check the number of arguments
78*7f8f2456SAndreas Gohr        if (count($args) != count($signature)) {
79*7f8f2456SAndreas Gohr            return new Error(-32602, 'server error. wrong number of method parameters');
80*7f8f2456SAndreas Gohr        }
81*7f8f2456SAndreas Gohr
82*7f8f2456SAndreas Gohr        // Check the argument types
83*7f8f2456SAndreas Gohr        $ok = true;
84*7f8f2456SAndreas Gohr        $argsbackup = $args;
85*7f8f2456SAndreas Gohr        for ($i = 0, $j = count($args); $i < $j; $i++) {
86*7f8f2456SAndreas Gohr            $arg = array_shift($args);
87*7f8f2456SAndreas Gohr            $type = array_shift($signature);
88*7f8f2456SAndreas Gohr            switch ($type) {
89*7f8f2456SAndreas Gohr                case 'int':
90*7f8f2456SAndreas Gohr                case 'i4':
91*7f8f2456SAndreas Gohr                    if (is_array($arg) || !is_int($arg)) {
92*7f8f2456SAndreas Gohr                        $ok = false;
93*7f8f2456SAndreas Gohr                    }
94*7f8f2456SAndreas Gohr                    break;
95*7f8f2456SAndreas Gohr                case 'base64':
96*7f8f2456SAndreas Gohr                case 'string':
97*7f8f2456SAndreas Gohr                    if (!is_string($arg)) {
98*7f8f2456SAndreas Gohr                        $ok = false;
99*7f8f2456SAndreas Gohr                    }
100*7f8f2456SAndreas Gohr                    break;
101*7f8f2456SAndreas Gohr                case 'boolean':
102*7f8f2456SAndreas Gohr                    if ($arg !== false && $arg !== true) {
103*7f8f2456SAndreas Gohr                        $ok = false;
104*7f8f2456SAndreas Gohr                    }
105*7f8f2456SAndreas Gohr                    break;
106*7f8f2456SAndreas Gohr                case 'float':
107*7f8f2456SAndreas Gohr                case 'double':
108*7f8f2456SAndreas Gohr                    if (!is_float($arg)) {
109*7f8f2456SAndreas Gohr                        $ok = false;
110*7f8f2456SAndreas Gohr                    }
111*7f8f2456SAndreas Gohr                    break;
112*7f8f2456SAndreas Gohr                case 'date':
113*7f8f2456SAndreas Gohr                case 'dateTime.iso8601':
114*7f8f2456SAndreas Gohr                    if (!($arg instanceof Date)) {
115*7f8f2456SAndreas Gohr                        $ok = false;
116*7f8f2456SAndreas Gohr                    }
117*7f8f2456SAndreas Gohr                    break;
118*7f8f2456SAndreas Gohr            }
119*7f8f2456SAndreas Gohr            if (!$ok) {
120*7f8f2456SAndreas Gohr                return new Error(-32602, 'server error. invalid method parameters');
121*7f8f2456SAndreas Gohr            }
122*7f8f2456SAndreas Gohr        }
123*7f8f2456SAndreas Gohr        // It passed the test - run the "real" method call
124*7f8f2456SAndreas Gohr        return parent::call($methodname, $argsbackup);
125*7f8f2456SAndreas Gohr    }
126*7f8f2456SAndreas Gohr
127*7f8f2456SAndreas Gohr    public function methodSignature($method)
128*7f8f2456SAndreas Gohr    {
129*7f8f2456SAndreas Gohr        if (!$this->hasMethod($method)) {
130*7f8f2456SAndreas Gohr            return new Error(-32601, 'server error. requested method "' . $method . '" not specified.');
131*7f8f2456SAndreas Gohr        }
132*7f8f2456SAndreas Gohr        // We should be returning an array of types
133*7f8f2456SAndreas Gohr        $types = $this->signatures[$method];
134*7f8f2456SAndreas Gohr        $return = [];
135*7f8f2456SAndreas Gohr        foreach ($types as $type) {
136*7f8f2456SAndreas Gohr            switch ($type) {
137*7f8f2456SAndreas Gohr                case 'string':
138*7f8f2456SAndreas Gohr                    $return[] = 'string';
139*7f8f2456SAndreas Gohr                    break;
140*7f8f2456SAndreas Gohr                case 'int':
141*7f8f2456SAndreas Gohr                case 'i4':
142*7f8f2456SAndreas Gohr                    $return[] = 42;
143*7f8f2456SAndreas Gohr                    break;
144*7f8f2456SAndreas Gohr                case 'double':
145*7f8f2456SAndreas Gohr                    $return[] = 3.1415;
146*7f8f2456SAndreas Gohr                    break;
147*7f8f2456SAndreas Gohr                case 'dateTime.iso8601':
148*7f8f2456SAndreas Gohr                    $return[] = new Date(time());
149*7f8f2456SAndreas Gohr                    break;
150*7f8f2456SAndreas Gohr                case 'boolean':
151*7f8f2456SAndreas Gohr                    $return[] = true;
152*7f8f2456SAndreas Gohr                    break;
153*7f8f2456SAndreas Gohr                case 'base64':
154*7f8f2456SAndreas Gohr                    $return[] = new Base64('base64');
155*7f8f2456SAndreas Gohr                    break;
156*7f8f2456SAndreas Gohr                case 'array':
157*7f8f2456SAndreas Gohr                    $return[] = ['array'];
158*7f8f2456SAndreas Gohr                    break;
159*7f8f2456SAndreas Gohr                case 'struct':
160*7f8f2456SAndreas Gohr                    $return[] = ['struct' => 'struct'];
161*7f8f2456SAndreas Gohr                    break;
162*7f8f2456SAndreas Gohr            }
163*7f8f2456SAndreas Gohr        }
164*7f8f2456SAndreas Gohr        return $return;
165*7f8f2456SAndreas Gohr    }
166*7f8f2456SAndreas Gohr
167*7f8f2456SAndreas Gohr    public function methodHelp($method)
168*7f8f2456SAndreas Gohr    {
169*7f8f2456SAndreas Gohr        return $this->help[$method];
170*7f8f2456SAndreas Gohr    }
171*7f8f2456SAndreas Gohr}
172