Passed
Push — master ( 775abc...0a1b69 )
by Phillip
01:18
created

ContainerResolver::getMethodInstanceArgs()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 7
nc 3
nop 1
dl 0
loc 13
ccs 8
cts 8
cp 1
crap 5
rs 9.6111
c 0
b 0
f 0
1
<?php
2
3
4
namespace Deployee\Components\Dependency;
5
6
use Deployee\Components\Container\ContainerException;
7
use Deployee\Components\Container\ContainerInterface;
8
9
class ContainerResolver
10
{
11
    /**
12
     * @var ContainerInterface
13
     */
14
    private $container;
15
16
    /**
17
     * @param ContainerInterface $container
18
     */
19 5
    public function __construct(ContainerInterface $container)
20
    {
21 5
        $this->container = $container;
22 5
    }
23
24
    /**
25
     * @param string $class
26
     * @param array $arguments
27
     * @return object
28
     * @throws \ReflectionException
29
     */
30 4
    public function createInstance(string $class, array $arguments = [])
31
    {
32 4
        $refl = new \ReflectionClass($class);
33 3
        $instanceArgs = count($arguments) === 0
34 3
            && $refl->getConstructor()
35 3
            && $refl->getConstructor()->isPublic()
36 3
            && $refl->getConstructor()->getNumberOfParameters() > 0
37 1
            ? $this->getMethodInstanceArgs($refl->getConstructor())
38 3
            : $arguments;
39
40 3
        $object = $refl->newInstanceArgs($instanceArgs);
41
42
43 3
        return $this->autowireObject($object);
44
    }
45
46
    /**
47
     * @param $object
48
     * @return mixed
49
     * @throws \ReflectionException
50
     */
51 4
    public function autowireObject($object)
52
    {
53 4
        if(!is_object($object)){
54 1
            throw new \InvalidArgumentException('Argument is not an object');
55
        }
56
57 3
        $refl = new \ReflectionClass($object);
58 3
        foreach($refl->getMethods(\ReflectionMethod::IS_PUBLIC) as $method){
59 3
            if($method->isConstructor()
60 3
                || $method->isDestructor()
61 3
                || !$method->isPublic()
62 3
                || $method->isStatic()
63 3
                || $method->getNumberOfParameters() !== 1
64 3
                || strpos($method->getName(), 'set') !== 0){
65 3
                continue;
66
            }
67
68 3
            $parameter = $this->getMethodInstanceArgs($method);
69 3
            if(count($parameter) > 0){
70 3
                $method->invoke($object, ...$parameter);
71
            }
72
        }
73
74 3
        return $object;
75
    }
76
77
    /**
78
     * @param \ReflectionMethod $method
79
     * @return array
80
     */
81 3
    private function getMethodInstanceArgs(\ReflectionMethod $method): array
82
    {
83 3
        $parameterList = [];
84 3
        foreach($method->getParameters() as $parameter){
85 3
            $type = (string)$parameter->getType();
86 3
            if(($value = $this->getContainerValue($type)) === null || (!class_exists($type) && !interface_exists($type))){
87 1
                return [];
88
            }
89
90 3
            $parameterList[] = $value;
91
        }
92
93 3
        return $parameterList;
94
    }
95
96
    /**
97
     * @param string $id
98
     * @return mixed
99
     */
100 3
    private function getContainerValue(string $id)
101
    {
102
        try{
103 3
            return $this->container->get($id);
104
        }
105 1
        catch(ContainerException $e){
106 1
            return $id === ContainerInterface::class ? $this->container : null;
107
        }
108
    }
109
}