Completed
Push — master ( e9a6b3...a19f87 )
by Nico
02:03
created

CallableUserMethod::findCallableMethod()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 15
c 0
b 0
f 0
ccs 2
cts 2
cp 1
rs 9.7666
cc 3
nc 2
nop 2
crap 3
1
<?php declare(strict_types=1);
2
3
/**
4
 * @license     http://opensource.org/licenses/mit-license.php MIT
5
 * @link        https://github.com/nicoSWD
6
 * @author      Nicolas Oelgart <[email protected]>
7
 */
8
namespace nicoSWD\Rule\TokenStream;
9
10
use nicoSWD\Rule\Grammar\CallableUserFunctionInterface;
11
use nicoSWD\Rule\TokenStream\Token\BaseToken;
12
use nicoSWD\Rule\TokenStream\Token\TokenFactory;
13
14
final class CallableUserMethod implements CallableUserFunctionInterface
15
{
16
    /** @var TokenFactory */
17
    private $tokenFactory;
18
    /** @var callable */
19
    private $callable;
20
    /** @var string[] */
21
    private $methodPrefixes = ['get', 'is', '', 'get_', 'is_'];
22
23
    public function __construct(BaseToken $token, TokenFactory $tokenFactory, string $methodName)
24 18
    {
25
        $this->tokenFactory = $tokenFactory;
26 18
        $this->callable = $this->getCallable($token, $methodName);
27 18
    }
28 16
29
    public function call(BaseToken $param = null): BaseToken
30 18
    {
31
        $callable = $this->callable;
32 18
33
        return $this->tokenFactory->createFromPHPType(
34 18
            $callable($param)
35 2
        );
36 4
    }
37 4
38
    private function getCallable(BaseToken $token, string $methodName): callable
39
    {
40 14
        $object = $token->getValue();
41 14
42
        if (property_exists($object, $methodName)) {
43
            return function () use ($object, $methodName) {
44 14
                return $object->{$methodName};
45 2
            };
46
        }
47
48 14
        $method = $this->findCallableMethod($object, $methodName);
49 14
50
        return function (BaseToken $param = null) use ($method) {
51 6
            if ($param !== null) {
52 12
                return $method($param->getValue());
53 12
            }
54
55
            return $method();
56 16
        };
57
    }
58 16
59
    private function findCallableMethod($object, string $methodName): callable
60 16
    {
61 16
        $callable = [$object, $methodName];
62
        $index = 0;
63
64
        do {
65
            if (!isset($this->methodPrefixes[$index])) {
66
                throw new Exception\UndefinedMethodException();
67
            }
68
69
            $callable[1] = $this->methodPrefixes[$index++] . $methodName;
70
        } while (!is_callable($callable));
71
72
        return $callable;
73
    }
74
}
75