Completed
Push — master ( 472b13...fcc7b0 )
by James Ekow Abaka
01:33
created

Container   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 105
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 83.33%

Importance

Changes 0
Metric Value
wmc 24
lcom 1
cbo 2
dl 0
loc 105
ccs 45
cts 54
cp 0.8333
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getResolvedClassName() 0 10 4
A bind() 0 4 1
A has() 0 4 1
A setup() 0 4 1
B resolve() 0 22 5
B getConstructorArguments() 0 15 5
A getSingletonInstance() 0 7 2
A getInstance() 0 15 4
1
<?php
2
3
namespace ntentan\panie;
4
5
/**
6
 * Description of Container
7
 *
8
 * @author ekow
9
 */
10
class Container
11
{
12
13
    private $bindings;
14
    private $singletons = [];
15
16 7
    public function __construct()
17
    {
18 7
        $this->bindings = new Bindings();
19 7
    }
20
21
    /**
22
     * 
23
     * @param string|\ReflectionClass $class
24
     * @return \ReflectionClass
25
     */
26 7
    private function getResolvedClassName($class)
27
    {
28 7
        $bound = null;
29 7
        if ($this->bindings->has($class)) {
30 5
            $bound = $this->bindings->get($class);
31 5
        } else if (is_string($class) && class_exists($class)) {
32 4
            $bound = ['binding' => $class];
33
        }
34 7
        return $bound;
35
    }
36
37 5
    public function bind($type)
38
    {
39 5
        return $this->bindings->setActiveKey($type);
40
    }
41
42
    public function has($type)
43
    {
44
        return $this->bindings->has($type);
45
    }
46
47
    public function setup($bindings)
48
    {
49
        $this->bindings->merge($bindings);
50
    }
51
52 7
    public function resolve($type, $constructorArguments = [])
53
    {
54 7
        if ($type === null) {
55
            throw new exceptions\ResolutionException("Cannot resolve an empty type");
56
        }
57 7
        $resolvedClass = $this->getResolvedClassName($type);
58 7
        if ($resolvedClass['binding'] === null) {
59 1
            throw new exceptions\ResolutionException("Could not resolve dependency $type");
60
        }
61 6
        if ($resolvedClass['singleton'] ?? false) {
62 1
            $instance = $this->getSingletonInstance($type, $resolvedClass['binding'], $constructorArguments);
63
        } else {
64 5
            $instance = $this->getInstance($resolvedClass['binding'], $constructorArguments);
65
        }
66
        
67 5
        foreach($resolvedClass['calls'] ?? [] as $method => $parameters) {
68
            $method = new \ReflectionMethod($instance, $method);
69
            $method->invokeArgs($instance, $this->getConstructorArguments($method, $parameters));
70
        }
71
        
72 5
        return $instance;
73
    }
74
75 3
    private function getConstructorArguments($constructor, $constructorArguments)
76
    {
77 3
        $argumentValues = [];
78 3
        $parameters = $constructor->getParameters();
79 3
        foreach ($parameters as $parameter) {
80 3
            $class = $parameter->getClass();
81 3
            $className = $class ? $class->getName() : null;
82 3
            if (isset($constructorArguments[$parameter->getName()])) {
83 1
                $argumentValues[] = $constructorArguments[$parameter->getName()];
84
            } else {
85 3
                $argumentValues[] = $className ? $this->resolve($className) : null;
86
            }
87
        }
88 3
        return $argumentValues;
89
    }
90
91 1
    private function getSingletonInstance($type, $class, $constructorArguments)
92
    {
93 1
        if (!isset($this->singletons[$type])) {
94 1
            $this->singletons[$type] = $this->getInstance($class, $constructorArguments);
95
        }
96 1
        return $this->singletons[$type];
97
    }
98
99 6
    private function getInstance($className, $constructorArguments = [])
100
    {
101 6
        if (is_callable($className)) {
102
            return $className($this);
103
        }
104 6
        $reflection = new \ReflectionClass($className);
105 6
        if ($reflection->isAbstract()) {
106 1
            throw new exceptions\ResolutionException(
107 1
            "Abstract class {$reflection->getName()} cannot be instantiated. "
1 ignored issue
show
Bug introduced by
Consider using $reflection->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
108 1
            . "Please provide a binding to an implementation."
109
            );
110
        }
111 5
        $constructor = $reflection->getConstructor();
112 5
        return $reflection->newInstanceArgs($constructor ? $this->getConstructorArguments($constructor, $constructorArguments) : []);
113
    }
114
}
115