Completed
Branch master (5720e6)
by Scott
05:47 queued 02:57
created

DotMethod::getInstanceMethod()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 5
cts 5
cp 1
rs 9.6666
c 0
b 0
f 0
cc 1
eloc 6
nc 1
nop 1
crap 1
1
<?php
2
namespace Desmond\functions\core;
3
use Desmond\functions\DesmondFunction;
4
use Desmond\data_types\ObjectType;
5
use Desmond\ArgumentHelper;
6
use Desmond\exceptions\ArgumentException;
7
use Exception;
8
9
class DotMethod implements DesmondFunction
10
{
11
    use \Desmond\TypeHelper;
12
    use ArgumentHelper;
13
14 155
    public function id()
15
    {
16 155
        return '.method';
17
    }
18
19 12
    public function run(array $args)
20
    {
21 12
        $this->checkFirstArgument($args);
22 10
        $target = $args[0]->value();
23 10
        if (is_string($target) && strpos($target, '::')) {
24 4
            return $this->callStaticMethod($target, $args);
25 6
        } else if (is_object($target)) {
26 5
            return $this->callInstanceMethod($target, $args);
27
        } else {
28 1
            throw new ArgumentException("\".method\": First argument must be an object or Class::method.");
29
        }
30
    }
31
32 12
    private function checkFirstArgument($args)
33
    {
34 12
        $this->expectArguments(
35 12
            '.method',
36 12
            [0 => ['Object', 'Symbol', 'String']],
37
            $args
38
        );
39 10
    }
40
41 5
    private function callInstanceMethod($object, $args)
42
    {
43 5
        $method = $this->getInstanceMethod($args);
44 4
        $this->checkInstanceMethodExists($object, $method);
45 3
        $methodArgs = array_slice($args, 2);
46 3
        foreach ($methodArgs as $key=> $arg) {
47 1
            $methodArgs[$key] = $arg->value();
48
        }
49 3
        return self::fromPhpType($object->$method(...$methodArgs));
50
    }
51
52 5
    private function getInstanceMethod($args)
53
    {
54 5
        $this->expectArguments(
55 5
            '.method',
56 5
            [1 => ['Symbol', 'String']],
57
            $args
58
        );
59 4
        return $args[1]->value();
60
    }
61
62 4
    private function callStaticMethod($method, $args)
63
    {
64 4
        $this->checkStaticExists($method);
65 2
        $methodArgs = array_slice($args, 1);
66 2
        foreach ($methodArgs as $key=> $arg) {
67 1
            $methodArgs[$key] = $arg->value();
68
        }
69 2
        return self::fromPhpType($method(...$methodArgs));
70
    }
71
72 4
    private function checkInstanceMethodExists($object, $method)
73
    {
74 4
        if (!method_exists($object, $method)) {
75 1
            $objectName = get_class($object);
76 1
            throw new ArgumentException("\".method\": Method \"$method\" not found in object \"$objectName\".");
77
        }
78 3
    }
79
80 4
    private function checkStaticExists($method)
81
    {
82 4
        $parts = explode('::', $method);
83 4
        if (!class_exists($parts[0])) {
84 1
            throw new ArgumentException("\".method\": Class \"{$parts[0]}\" not found.");
85
        }
86 3
        if (!method_exists($parts[0], $parts[1])) {
87 1
            throw new ArgumentException('".method": Method "' . $parts[1] . '" not found in class "' . $parts[0] . '".');
88
        }
89 2
    }
90
}
91