Completed
Push — master ( eed05d...5ff1a2 )
by James Ekow Abaka
01:21
created

Container   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 104
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 83.64%

Importance

Changes 0
Metric Value
wmc 25
lcom 1
cbo 2
dl 0
loc 104
ccs 46
cts 55
cp 0.8364
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
A resolve() 0 15 4
B getConstructorArguments() 0 17 6
A getSingletonInstance() 0 7 2
B getInstance() 0 19 5
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
    public 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, $replace = true)
48
    {
49
        $this->bindings->merge($bindings, $replace);
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
            return $this->getSingletonInstance($type, $resolvedClass['binding'], $constructorArguments);
63
        } else {
64 5
            return $this->getInstance($resolvedClass['binding'], $constructorArguments);
65
        }
66
    }
67
68 3
    private function getConstructorArguments($constructor, $constructorArguments)
69
    {
70 3
        $argumentValues = [];
71 3
        $parameters = $constructor->getParameters();
72 3
        foreach ($parameters as $parameter) {
73 3
            $class = $parameter->getClass();
74 3
            $className = $class ? $class->getName() : null;
75 3
            if (isset($constructorArguments[$parameter->getName()])) {
76 1
                $argumentValues[] = $constructorArguments[$parameter->getName()];
77 3
            } else if ($className == self::class) {
78
                $argumentValues[] = $this;
79
            } else {
80 3
                $argumentValues[] = $className ? $this->resolve($className) : null;
81
            }
82
        }
83 3
        return $argumentValues;
84
    }
85
86 1
    private function getSingletonInstance($type, $class, $constructorArguments)
87
    {
88 1
        if (!isset($this->singletons[$type])) {
89 1
            $this->singletons[$type] = $this->getInstance($class, $constructorArguments);
90
        }
91 1
        return $this->singletons[$type];
92
    }
93
94 6
    public function getInstance($className, $constructorArguments = [])
95
    {
96 6
        if (is_callable($className)) {
97
            return $className($this);
98
        }
99 6
        if (is_object($className)) {
100
            return $className;
101
        }
102 6
        $reflection = new \ReflectionClass($className);
103 6
        if ($reflection->isAbstract()) {
104 1
            throw new exceptions\ResolutionException(
105 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...
106 1
            . "Please provide a binding to an implementation."
107
            );
108
        }
109 5
        $constructor = $reflection->getConstructor();
110 5
        $instance = $reflection->newInstanceArgs($constructor ? $this->getConstructorArguments($constructor, $constructorArguments) : []);
111 5
        return $instance;
112
    }
113
}
114