Completed
Push — master ( c31a8f...f0cf24 )
by Dmitrij
9s
created

AppContainer::resolveWithoutConstructor()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
namespace HotRodCli;
4
5
class AppContainer
6
{
7
    /**
8
     * All registered.
9
     * ----------------------------------------
10
     * @var array
11
     */
12
    protected $registry = [];
13
14
    public function resolve(string $class, $args = null)
15
    {
16
        if (array_key_exists($class, $this->registry)) {
17
            return $this->registry[$class];
18
        }
19
20
        $reflector = new \ReflectionClass($class);
21
22
        if (!$reflector->isInstantiable()) {
23
            throw new \Exception("[$class] is not instantiable");
24
        }
25
26
        $constructor = $reflector->getConstructor();
27
28
        if (is_null($constructor)) {
29
            return $this->resolveWithoutConstructor($class);
30
        }
31
32
        if (!is_null($args)) {
33
            return $this->resolveWithSetParams($class, $args);
34
        }
35
36
        $parameters = $constructor->getParameters();
37
        $dependencies = $this->getDependencies($parameters);
38
39
        $result = $reflector->newInstanceArgs($dependencies);
40
        $this->bind($class, $result);
41
42
        return $result;
43
    }
44
45
    protected function resolveWithoutConstructor(string $class)
46
    {
47
        $result = new $class;
48
        $this->bind($class, $result);
49
50
        return $result;
51
    }
52
53
    protected function resolveWithSetParams(string $class, $args)
54
    {
55
        $reflector = new \ReflectionClass($class);
56
        $result = $reflector->newInstance($args);
57
        $this->bind($class, $result);
58
59
        return $result;
60
    }
61
62
    /**
63
     * @param $parameters
64
     * @return array
65
     */
66
    public function getDependencies($parameters)
67
    {
68
        $dependencies = [];
69
70
        /** @var \ReflectionParameter $parameter */
71
        foreach ($parameters as $parameter) {
72
            $dependency = $parameter->getClass();
73
74
            if (is_null($dependency)) {
75
                $dependencies[] = $this->resolveNonClass($parameter);
76
            } else {
77
                $dependencies[] = $this->resolve($dependency->name);
78
            }
79
        }
80
81
        return $dependencies;
82
    }
83
84
    /**
85
     * @param $key
86
     * @param $value
87
     * @throws \Exception
88
     */
89
    public function bind($key, $value)
90
    {
91
        if (! array_key_exists($key, $this->registry)) {
92
            $this->registry[$key] = $value;
93
        } else {
94
            throw new \Exception("{$key} is already bound in the container.");
95
        }
96
    }
97
98
    /**
99
     * @param $key
100
     * @return mixed
101
     * @throws \Exception
102
     */
103
    public function get($key)
104
    {
105
        if (! array_key_exists($key, $this->registry)) {
106
            throw new \Exception("No {$key} is bound in the container.");
107
        }
108
109
        return $this->registry[$key];
110
    }
111
112
    /**
113
     * @param \ReflectionParameter $parameter
114
     * @return mixed
115
     * @throws \Exception
116
     */
117
    public function resolveNonClass(\ReflectionParameter $parameter)
118
    {
119
        if ($parameter->isDefaultValueAvailable()) {
120
            return $parameter->getDefaultValue();
121
        }
122
123
        throw new \Exception("Cannot resolve the unknown");
124
    }
125
}
126