Completed
Push — master ( 23b6a7...8b7e63 )
by James Ekow Abaka
01:56
created

Container::getInstance()   C

Complexity

Conditions 7
Paths 3

Size

Total Lines 27
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 27
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 19
nc 3
nop 2
1
<?php
2
3
namespace ntentan\panie;
4
5
/**
6
 * Description of Container
7
 *
8
 * @author ekow
9
 */
10
class Container {
11
12
    private $bindings;
13
    private $singletons = [];
14
15
    public function __construct() {
16
        $this->bindings = new Bindings();
17
    }
18
19
    /**
20
     * 
21
     * @param string|\ReflectionClass $class
22
     * @return \ReflectionClass
23
     */
24
    public function getResolvedClassName($class) {
25
        $bound = null;
26
        if ($this->bindings->has($class)) {
27
            $bound = $this->bindings->get($class);
28
        } else if (is_string($class) && class_exists($class)) {
29
            $bound = ['class' => $class];
30
        }     
31
        return $bound;
32
    }
33
34
    public function bind($lose) {
35
        return $this->bindings->setActiveKey($lose);
36
    }
37
38
    public function singleton($type, $constructorArguments = []) {
39
        $resolvedClass = $this->getResolvedClassName($type)['class'];
40
        return $this->getSingletonInstance($type, $resolvedClass, $constructorArguments);
41
    }
42
    
43
    private function getSingletonInstance($type, $class,  $constructorArguments) {
44
        if (!isset($this->singletons[$type])) {
45
            $this->singletons[$type] = $this->getInstance($class, $constructorArguments);
46
        }
47
        return $this->singletons[$type];        
48
    }
49
    
50
    public function resolve($type, $constructorArguments = []) {
51
        if($type === null) {
52
            throw new exceptions\ResolutionException("Cannot resolve an empty type");
53
        }
54
        $resolvedClass = $this->getResolvedClassName($type);
55
        if ($resolvedClass['class'] === null) {
56
            throw new exceptions\ResolutionException("Could not resolve dependency $type");
57
        }           
58
        if(isset($resolvedClass['singleton'])) {
59
            return $this->getSingletonInstance($type, $resolvedClass['class'], $constructorArguments);
60
        } else {
61
            return $this->getInstance($resolvedClass['class'], $constructorArguments);
62
        }
63
    }
64
65
    public function getInstance($className, $constructorArguments = []) {
66
        
67
        $reflection = new \ReflectionClass($className);
68
        if ($reflection->isAbstract()) {
69
            throw new exceptions\ResolutionException(
70
            "Abstract class {$reflection->getName()} cannot be instantiated. "
71
            . "Please provide a binding to an implementation."
72
            );
73
        }
74
        $constructor = $reflection->getConstructor();
75
        $instanceParameters = [];
76
77
        if ($constructor != null) {
78
            $parameters = $constructor->getParameters();
79
            foreach ($parameters as $parameter) {
80
                $class = $parameter->getClass();
81
                if (isset($constructorArguments[$parameter->getName()])) {
82
                    $instanceParameters[] = $constructorArguments[$parameter->getName()];
83
                } else if($class == self::class){
84
                    $instanceParameters[] = $this;
85
                } else {                    
86
                    $instanceParameters[] = $class ? $this->resolve($class->getName()) : null;
87
                }
88
            }
89
        }
90
        return $reflection->newInstanceArgs($instanceParameters);
91
    }
92
93
}
94