Completed
Push — spike ( 2414ba )
by Akihito
06:46
created

AssistedInterceptor::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
crap 2
1
<?php
2
3
declare(strict_types=1);
4
/**
5
 * This file is part of the Ray.Di package.
6
 *
7
 * @license http://opensource.org/licenses/MIT MIT
8
 */
9
namespace Ray\Di;
10
11
use Ray\Aop\MethodInterceptor;
12
use Ray\Aop\MethodInvocation;
13
use Ray\Aop\ReflectionMethod;
14
use Ray\Di\Di\Assisted;
15
use Ray\Di\Di\Named;
16
17
final class AssistedInterceptor implements MethodInterceptor
18
{
19
    /**
20
     * @var InjectorInterface
21
     */
22
    private $injector;
23
24
    /**
25
     * @var MethodInvocationProvider
26
     */
27
    private $methodInvocationProvider;
28
29
    public function __construct(InjectorInterface $injector, MethodInvocationProvider $methodInvocationProvider)
30
    {
31
        $this->injector = $injector;
32
        $this->methodInvocationProvider = $methodInvocationProvider;
33
    }
34
35
    /**
36
     * Intercepts any method and injects instances of the missing arguments
37
     * when they are type hinted
38
     *
39
     * @return object
40
     */
41
    public function invoke(MethodInvocation $invocation)
42
    {
43
        /** @var ReflectionMethod $method */
44
        $method = $invocation->getMethod();
45
        $assisted = $method->getAnnotation(Assisted::class);
46
        /* @var \Ray\Di\Di\Assisted $assisted */
47
        $parameters = $method->getParameters();
48
        $arguments = $invocation->getArguments()->getArrayCopy();
49
        if ($assisted instanceof Assisted && $method instanceof ReflectionMethod) {
50
            $this->methodInvocationProvider->set($invocation);
51
            $arguments = $this->injectAssistedParameters($method, $assisted, $parameters, $arguments);
52
        }
53
        $invocation->getArguments()->exchangeArray($arguments);
54
55
        return $invocation->proceed();
56
    }
57
58
    /**
59
     * @internal param int $cntArgs
60
     */
61
    public function injectAssistedParameters(ReflectionMethod $method, Assisted $assisted, array $parameters, array $arguments) : array
62
    {
63
        foreach ($parameters as $parameter) {
64
            if (! \in_array($parameter->getName(), $assisted->values, true)) {
65
                continue;
66
            }
67
            /* @var $parameter \ReflectionParameter */
68
            $hint = $parameter->getClass();
69
            $interface = $hint ? $hint->getName() : '';
0 ignored issues
show
Bug introduced by
Consider using $hint->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
70
            $name = $this->getName($method, $parameter);
71
            $pos = $parameter->getPosition();
72
            $arguments[$pos] = $this->injector->getInstance($interface, $name);
73
        }
74
75
        return $arguments;
76
    }
77
78
    /**
79
     * Return dependency "name"
80
     */
81
    private function getName(ReflectionMethod $method, \ReflectionParameter $parameter) : string
82
    {
83
        $named = $method->getAnnotation(Named::class);
84
        if (! $named instanceof Named) {
85
            return Name::ANY;
86
        }
87
        parse_str($named->value, $names);
88
        $paramName = $parameter->getName();
0 ignored issues
show
Bug introduced by
Consider using $parameter->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
89
        if (isset($names[$paramName])) {
90
            return $names[$paramName];
91
        }
92
93
        return Name::ANY;
94
    }
95
}
96