RpcMethod   A
last analyzed

Complexity

Total Complexity 34

Size/Duplication

Total Lines 376
Duplicated Lines 0 %

Test Coverage

Coverage 92.75%

Importance

Changes 0
Metric Value
wmc 34
dl 0
loc 376
ccs 64
cts 69
cp 0.9275
rs 9.68
c 0
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
A create() 0 9 2
A getParameters() 0 5 2
A getArguments() 0 3 1
A __construct() 0 13 3
A selectSignature() 0 11 3
A addParameter() 0 9 3
A deleteParameter() 0 7 2
A getDescription() 0 3 1
A getSignatures() 0 17 3
A addSignature() 0 12 1
A getCallback() 0 3 1
A setDescription() 0 9 3
A deleteSignature() 0 11 3
A getName() 0 3 1
A setReturnType() 0 7 2
A getSignature() 0 9 2
A getReturnType() 0 3 1
1
<?php namespace Comodojo\RpcServer;
2
3
use \InvalidArgumentException;
4
use \Exception;
5
6
/**
7
 * RPC Method object
8
 *
9
 * It create a method's object ready to inject into RpcServer.
10
 *
11
 * @package     Comodojo Spare Parts
12
 * @author      Marco Giovinazzi <[email protected]>
13
 * @license     MIT
14
 *
15
 * LICENSE:
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
 * THE SOFTWARE.
24
 */
25
26
class RpcMethod {
27
28
    const FETCH_ASSOC = 'ASSOC';
29
30
    const FETCH_NUMERIC = "NUMERIC";
31
32
    /**
33
     * Generic-to-RPC values map
34
     *
35
     * @var array $rpcvalues
36
     */
37
    public static $rpcvalues = array(
38
        "i4" => "int",
39
        "int" => "int",
40
        "integer" => "int",
41
        "double" => "double",
42
        "float" => "double",
43
        "boolean" => "boolean",
44
        "bool" => "boolean",
45
        "base64" => "base64",
46
        "dateTime.iso8601" => "dateTime.iso8601",
47
        "datetime" => "dateTime.iso8601",
48
        "string" => "string",
49
        "array" => "array",
50
        "struct" => "struct",
51
        "nil" => "null",
52
        "ex:nil" => "null",
53
        "null" => "null",
54
        "undefined" => "undefined"
55
    );
56
57
    /**
58
     * Name of method
59
     *
60
     * @var string
61
     */
62
    private $name;
63
64
    /**
65
     * Callback class|function
66
     *
67
     * @var callable
68
     */
69
    private $callback;
70
71
    /**
72
     * Description of method
73
     *
74
     * @var string
75
     */
76
    private $description;
77
78
    /**
79
     * Array of supported signatures
80
     *
81
     * @var array
82
     */
83
    private $signatures = [];
84
85
    /**
86
     * Internal pointer to current signature
87
     *
88
     * @var int
89
     */
90
    private $current_signature;
91
92
    /**
93
     * Placeholder for additional arguments
94
     *
95
     * @var array
96
     */
97
    private $arguments = [];
98
99
    /**
100
     * Class constructor
101
     *
102
     * @param string $name
103
     * @param callable  $callback
104
     *
105
     * @throws InvalidArgumentException
106
     */
107 93
    public function __construct($name, callable $callback, ...$arguments) {
108
109 93
        if ( empty($name) ) throw new InvalidArgumentException("Invalid or undefined RpcMethod name");
110
111 93
        if ( !is_callable($callback) ) throw new InvalidArgumentException("Invalid or undefined RpcMethod callback");
112
113 93
        $this->name = $name;
114
115 93
        $this->callback = $callback;
116
117 93
        $this->arguments = $arguments;
118
119 93
        $this->addSignature();
120
121 93
    }
122
123
    /**
124
     * Get the method's name
125
     *
126
     * @return string
127
     */
128 93
    public function getName() {
129
130 93
        return $this->name;
131
132
    }
133
134
    /**
135
     * Get the method's callback
136
     *
137
     * @return callable
138
     */
139 81
    public function getCallback() {
140
141 81
        return $this->callback;
142
143
    }
144
145
    /**
146
     * Set the method's description
147
     *
148
     * @param string $description
149
     *
150
     * @return self
151
     * @throws InvalidArgumentException
152
     */
153 93
    public function setDescription($description = null) {
154
155 93
        if ( empty($description) ) $this->description = null;
156
157 93
        else if ( !is_string($description) ) throw new InvalidArgumentException("Invalid RpcMethod description");
0 ignored issues
show
introduced by
The condition is_string($description) is always true.
Loading history...
158
159 93
        else $this->description = $description;
160
161 93
        return $this;
162
163
    }
164
165
    /**
166
     * Get the method's method
167
     *
168
     * @return string|null
169
     */
170 15
    public function getDescription() {
171
172 15
        return $this->description;
173
174
    }
175
176
    /**
177
     * Get additional arguments to forward to callback
178
     *
179
     * @return array
180
     */
181 78
    public function getArguments() {
182
183 78
        return $this->arguments;
184
185
    }
186
187
    /**
188
     * Add a signature and switch internal pointer
189
     *
190
     * @return self
191
     */
192 93
    public function addSignature() {
193
194
        $signature = [
195 93
            "PARAMETERS" => [],
196
            "RETURNTYPE" => 'undefined'
197
        ];
198
199 93
        array_push($this->signatures, $signature);
200
201 93
        $this->current_signature = max(array_keys($this->signatures));
202
203 93
        return $this;
204
205
    }
206
207
    /**
208
     * Get the method's signatures
209
     *
210
     * @param bool $compact (default) Compact signatures in a format compatible with system.methodSignature
211
     *
212
     * @return array
213
     */
214 81
    public function getSignatures($compact = true) {
215
216 81
        if ( $compact ) {
217
218 18
            $signatures = [];
219
220 18
            foreach ( $this->signatures as $signature ) {
221
222 18
                $signatures[] = array_merge([$signature["RETURNTYPE"]], array_values($signature["PARAMETERS"]));
223
224
            }
225
226 18
            return $signatures;
227
228
        } else {
229
230 78
            return $this->signatures;
231
232
        }
233
234
    }
235
236
    /**
237
     * Get the current method's signature
238
     *
239
     * @param bool $compact (default) Compact signatures in a format compatible with system.methodSignature
240
     *
241
     * @return array
242
     */
243 3
    public function getSignature($compact = true) {
244
245 3
        if ( $compact ) {
246
247 3
            return array_merge([$this->signatures[$this->current_signature]["RETURNTYPE"]], array_values($this->signatures[$this->current_signature]["PARAMETERS"]));
248
249
        } else {
250
251
            return $this->signatures[$this->current_signature];
252
253
        }
254
255
    }
256
257
    /**
258
     * Delete a signature
259
     *
260
     * @param integer $signature The signature's ID
261
     *
262
     * @return bool
263
     * @throws InvalidArgumentException
264
     */
265 3
    public function deleteSignature($signature) {
266
267 3
        if ( !is_integer($signature) || !isset($this->signatures[$signature]) ) {
0 ignored issues
show
introduced by
The condition is_integer($signature) is always true.
Loading history...
268
269
            throw new InvalidArgumentException("Invalid RpcMethod signature reference");
270
271
        }
272
273 3
        unset($this->signatures[$signature]);
274
275 3
        return true;
276
277
    }
278
279
    /**
280
     * Select a signature
281
     *
282
     * @param integer $signature The signature's ID
283
     *
284
     * @return self
285
     * @throws Exception
286
     */
287 81
    public function selectSignature($signature) {
288
289 81
        if ( !is_integer($signature) || !isset($this->signatures[$signature]) ) {
0 ignored issues
show
introduced by
The condition is_integer($signature) is always true.
Loading history...
290
291
            throw new InvalidArgumentException("Invalid RpcMethod signature reference");
292
293
        }
294
295 81
        $this->current_signature = $signature;
296
297 81
        return $this;
298
299
    }
300
301
    /**
302
     * Set the current signature's return type
303
     *
304
     * @param string $type
305
     *
306
     * @return self
307
     * @throws InvalidArgumentException
308
     */
309 93
    public function setReturnType($type) {
310
311 93
        if ( !in_array($type, self::$rpcvalues) ) throw new InvalidArgumentException("Invalid RpcMethod return type");
312
313 93
        $this->signatures[$this->current_signature]["RETURNTYPE"] = self::$rpcvalues[$type];
314
315 93
        return $this;
316
317
    }
318
319
    /**
320
     * Get the current signature's return type
321
     *
322
     * @return string
323
     */
324 3
    public function getReturnType() {
325
326 3
        return $this->signatures[$this->current_signature]["RETURNTYPE"];
327
328
    }
329
330
    /**
331
     * Add a parameter to current signature
332
     *
333
     * @param string $type
334
     * @param string $name
335
     *
336
     * @return self
337
     * @throws InvalidArgumentException
338
     */
339 90
    public function addParameter($type, $name) {
340
341 90
        if ( !in_array($type, self::$rpcvalues) ) throw new InvalidArgumentException("Invalid type for parameter $name");
342
343 90
        if ( empty($name) ) throw new InvalidArgumentException("Missing parameter name");
344
345 90
        $this->signatures[$this->current_signature]["PARAMETERS"][$name] = self::$rpcvalues[$type];
346
347 90
        return $this;
348
349
    }
350
351
    /**
352
     * Delete a parameter from current signature
353
     *
354
     * @param string $name
355
     *
356
     * @return self
357
     * @throws Exception
358
     */
359 3
    public function deleteParameter($name) {
360
361 3
        if ( !array_key_exists($name, $this->signatures[$this->current_signature]["PARAMETERS"]) ) throw new Exception("Cannot find parameter $name");
362
363 3
        unset($this->signatures[$this->current_signature]["PARAMETERS"][$name]);
364
365 3
        return $this;
366
367
    }
368
369
    /**
370
     * Get current signature's parameters
371
     *
372
     * @param string $format The output array format (ASSOC|NUMERIC)
373
     *
374
     * @return array
375
     */
376 81
    public function getParameters($format = self::FETCH_ASSOC) {
377
378 81
        if ( $format === self::FETCH_NUMERIC ) return array_values($this->signatures[$this->current_signature]["PARAMETERS"]);
379
380 81
        else return $this->signatures[$this->current_signature]["PARAMETERS"];
381
382
    }
383
384
    /**
385
     * Static class constructor - create an RpcMethod object
386
     *
387
     * @param string $name
388
     * @param string $callback
389
     *
390
     * @return RpcMethod
391
     * @throws Exception
392
     */
393 93
    public static function create($name, callable $callback, ...$arguments) {
394
395
        try {
396
397 93
            return  new RpcMethod($name, $callback, ...$arguments);
398
399
        } catch (Exception $e) {
400
401
            throw $e;
402
403
        }
404
405
    }
406
407
}
408