Completed
Push — 2.0 ( 96404c...7f22ab )
by Marco
13:11
created

RpcMethod::getArguments()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php namespace Comodojo\RpcServer;
2
3
use \Exception;
4
5
/**
6
 * RPC Method object
7
 *
8
 * It create a method's object ready to inject into RpcServer.
9
 *
10
 * @package     Comodojo Spare Parts
11
 * @author      Marco Giovinazzi <[email protected]>
12
 * @license     MIT
13
 *
14
 * LICENSE:
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
25
class RpcMethod {
26
27
    /**
28
     * Generic-to-RPC values map
29
     *
30
     * @var array $rpcvalues
31
     */
32
    public static $rpcvalues = array(
33
        "i4" => "int",
34
        "int" => "int",
35
        "double" => "double",
36
        "float" => "double",
37
        "boolean" => "boolean",
38
        "bool" => "boolean",
39
        "base64" => "base64",
40
        "dateTime.iso8601" => "dateTime.iso8601",
41
        "datetime" => "dateTime.iso8601",
42
        "string" => "string",
43
        "array" => "array",
44
        "struct" => "struct",
45
        "nil" => "null",
46
        "ex:nil" => "null",
47
        "null" => "null",
48
        "undefined" => "undefined"
49
    );
50
51
    /**
52
     * Name of method
53
     *
54
     * @var string
55
     */
56
    private $name = null;
57
58
    /**
59
     * Callback class|function
60
     *
61
     * @var string|function
62
     */
63
    private $callback = null;
64
65
    /**
66
     * Description of method
67
     *
68
     * @var string
69
     */
70
    private $description = null;
71
72
    /**
73
     * Array of supported signatures
74
     *
75
     * @var array
76
     */
77
    private $signatures = array();
78
79
    /**
80
     * Internal pointer to current signature
81
     *
82
     * @var int
83
     */
84
    private $current_signature = null;
85
86
    /**
87
     * Placeholder for additional arguments
88
     *
89
     * @var array
90
     */
91
    private $arguments = array();
92
93
    /**
94
     * Class constructor
95
     *
96
     * @param string $name
97
     * @param mixed  $callback
98
     * @param string $method
0 ignored issues
show
Bug introduced by
There is no parameter named $method. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
99
     *
100
     * @throws Exception
101
     */
102
    public function __construct($name, callable $callback, ...$arguments) {
103
104
        if ( !is_string($name) ) throw new Exception("RPC method exception: invalid or undefined name");
105
106
        if ( !is_callable($callback) ) throw new Exception("RPC method exception, invalid or undefined callback");
107
108
        $this->name = $name;
109
110
        $this->callback = $callback;
0 ignored issues
show
Documentation Bug introduced by
It seems like $callback of type callable is incompatible with the declared type string|object<Comodojo\RpcServer\function> of property $callback.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
111
112
        $this->arguments = $arguments;
113
114
        $this->addSignature();
115
116
    }
117
118
    /**
119
     * Get the method's name
120
     *
121
     * @return string
122
     */
123
    public function getName() {
124
125
        return $this->name;
126
127
    }
128
129
    /**
130
     * Get the method's callback
131
     *
132
     * @return callable
133
     */
134
    public function getCallback() {
135
136
        return $this->callback;
137
138
    }
139
140
    /**
141
     * Set the method's description
142
     *
143
     * @param string $description
144
     *
145
     * @return $this
146
     */
147
    public function setDescription($description = null) {
148
149
        if ( empty($description) ) $this->description = null;
150
151
        else if ( !is_string($description) ) throw new Exception("RPC method exception: invalid description");
152
153
        else $this->description = $description;
154
155
        return $this;
156
157
    }
158
159
    /**
160
     * Get the method's method
161
     *
162
     * @return string|null
163
     */
164
    public function getDescription() {
165
166
        return $this->description;
167
168
    }
169
170
    /**
171
     * Get additional arguments to forward to callback
172
     *
173
     * @return array
174
     */
175
    public function getArguments() {
176
177
        return $this->arguments;
178
179
    }
180
181
    /**
182
     * Add a signature and switch internal pointer
183
     *
184
     * @return $this
185
     */
186
    public function addSignature() {
187
188
        $signature = array(
189
            "PARAMETERS" => array(),
190
            "RETURNTYPE" => 'undefined'
191
        );
192
193
        array_push($this->signatures, $signature);
194
195
        $this->current_signature = max(array_keys($this->signatures));
0 ignored issues
show
Documentation Bug introduced by
It seems like max(array_keys($this->signatures)) can also be of type string. However, the property $current_signature is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
196
197
        return $this;
198
199
    }
200
201
    /**
202
     * Get the method's signatures
203
     *
204
     * @param bool $compact (default) Compact signatures in a format compatible with system.methodSignature
205
     *
206
     * @return array
207
     */
208
    public function getSignatures($compact = true) {
209
210
        if ( $compact ) {
211
212
            $signatures = array();
213
214
            foreach ( $this->signatures as $signature ) {
215
216
                $signatures[] = array_merge(array($signature["RETURNTYPE"]), array_values($signature["PARAMETERS"]));
217
218
            }
219
220
            return $signatures;
221
222
        } else {
223
224
            return $this->signatures;
225
226
        }
227
228
    }
229
230
    /**
231
     * Get the current method's signature
232
     *
233
     * @param bool $compact (default) Compact signatures in a format compatible with system.methodSignature
234
     *
235
     * @return array
236
     */
237
    public function getSignature($compact = true) {
238
239
        if ( $compact ) {
240
241
            return array_merge(array($this->signatures[$this->current_signature]["RETURNTYPE"]), array_values($this->signatures[$this->current_signature]["PARAMETERS"]));
242
243
        } else {
244
245
            return $this->signatures[$this->current_signature];
246
247
        }
248
249
    }
250
251
    /**
252
     * Delete a signature
253
     *
254
     * @param integer $signature The signature's ID
255
     *
256
     * @return bool
257
     * @throws Exception
258
     */
259 View Code Duplication
    public function deleteSignature($signature) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
260
261
        if ( !is_integer($signature) || !isset($this->signatures[$signature]) ) {
262
263
            throw new Exception("RPC method exception: invalid signature reference");
264
265
        }
266
267
        unset($this->signatures[$signature]);
268
269
        return true;
270
271
    }
272
273
    /**
274
     * Select a signature
275
     *
276
     * @param integer $signature The signature's ID
277
     *
278
     * @return $this
279
     * @throws Exception
280
     */
281 View Code Duplication
    public function selectSignature($signature) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
282
283
        if ( !is_integer($signature) || !isset($this->signatures[$signature]) ) {
284
285
            throw new Exception("RPC method exception: invalid signature reference");
286
287
        }
288
289
        $this->current_signature = $signature;
290
291
        return $this;
292
293
    }
294
295
    /**
296
     * Set the current signature's return type
297
     *
298
     * @param string $type
299
     *
300
     * @return $this
301
     * @throws Exception
302
     */
303
    public function setReturnType($type) {
304
305
        if ( !in_array($type, self::$rpcvalues) ) throw new Exception("RPC method exception: invalid return type");
306
307
        $this->signatures[$this->current_signature]["RETURNTYPE"] = self::$rpcvalues[$type];
308
309
        return $this;
310
311
    }
312
313
    /**
314
     * Get the current signature's return type
315
     *
316
     * @return string
317
     */
318
    public function getReturnType() {
319
320
        return $this->signatures[$this->current_signature]["RETURNTYPE"];
321
322
    }
323
324
    /**
325
     * Add a parameter to current signature
326
     *
327
     * @param string $type
328
     * @param string $name
329
     *
330
     * @return $this
331
     * @throws Exception
332
     */
333
    public function addParameter($type, $name) {
334
335
        if ( !in_array($type, self::$rpcvalues) ) throw new Exception("RPC method exception: invalid parameter type");
336
337
        if ( empty($name) ) throw new Exception("RPC method exception: invalid parameter name");
338
339
        $this->signatures[$this->current_signature]["PARAMETERS"][$name] = self::$rpcvalues[$type];
340
341
        return $this;
342
343
    }
344
345
    /**
346
     * Delete a parameter from current signature
347
     *
348
     * @param string $name
349
     *
350
     * @return $this
351
     * @throws Exception
352
     */
353
    public function deleteParameter($name) {
354
355
        if ( !array_key_exists($name, $this->signatures[$this->current_signature]["PARAMETERS"]) ) throw new Exception("RPC method exception: cannot find parameter");
356
357
        unset($this->signatures[$this->current_signature]["PARAMETERS"][$name]);
358
359
        return $this;
360
361
    }
362
363
    /**
364
     * Get current signature's parameters
365
     *
366
     * @param string $format The output array format (ASSOC|NUMERIC)
367
     *
368
     * @return array
369
     */
370
    public function getParameters($format = 'ASSOC') {
371
372
        if ( $format == 'NUMERIC' ) return array_values($this->signatures[$this->current_signature]["PARAMETERS"]);
373
374
        else return $this->signatures[$this->current_signature]["PARAMETERS"];
375
376
    }
377
378
    /**
379
     * Static class constructor - create an RpcMethod object
380
     *
381
     * @param string            $name
382
     * @param string|function   $callback
383
     * @param string|null       $method
0 ignored issues
show
Bug introduced by
There is no parameter named $method. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
384
     *
385
     * @return RpcMethod
386
     * @throws Exception
387
     */
388
    public static function create($name, $callback, ...$attributes) {
389
390
        try {
391
392
            $method = new RpcMethod($name, $callback, ...$attributes);
393
394
        } catch (Exception $e) {
395
396
            throw $e;
397
398
        }
399
400
        return $method;
401
402
    }
403
404
}
405