Completed
Push — master ( 2e24f4...41a1dd )
by Jesse
02:43
created

AutoWiring::the()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stratadox\Di;
6
7
use ReflectionClass;
8
9
final class AutoWiring
10
{
11
    private $container;
12
    private $links;
13
14
    private function __construct(ContainerInterface $container, array $links)
15
    {
16
        $this->container = $container;
17
        $this->links = $links;
18
    }
19
20
    public static function the(ContainerInterface $container) : self
21
    {
22
        return new self($container, []);
23
    }
24
25
    public function link(string $interface, string $class) : self
26
    {
27
        return new self($this->container, [$interface => $class] + $this->links);
28
    }
29
30
    public function get(string $service)
31
    {
32
        if (!$this->container->has($service)) {
33
            $this->resolve($service);
34
        }
35
        return $this->container->get($service);
36
    }
37
38
    public function has(string $service) : bool
39
    {
40
        return class_exists($service) || interface_exists($service);
41
    }
42
43
    private function resolve(string $service)
44
    {
45
        if (interface_exists($service)) {
46
            $this->resolveInterface($service);
47
        } else {
48
            $this->resolveClass($service);
49
        }
50
    }
51
52
    private function resolveInterface(string $service)
53
    {
54
        $class = $this->links[$service];
55
        $this->resolveClass($class);
56
        $this->container->set($service, function () use ($class) {
57
            return $this->container->get($class);
58
        });
59
    }
60
61
    private function resolveClass(string $service)
62
    {
63
        $constructor = (new ReflectionClass($service))->getConstructor();
64
        $dependencies = [];
65
        if (isset($constructor)) {
66
            foreach ($constructor->getParameters() as $parameter) {
67
                $dependency = (string) $parameter->getType();
68
                $this->resolve($dependency);
69
                $dependencies[] = $dependency;
70
            }
71
        }
72
        $this->container->set($service,
73
            function () use ($service, $dependencies) {
74
                $parameters = [];
75
                foreach ($dependencies as $dependency) {
76
                    $parameters[] = $this->container->get($dependency);
77
                }
78
                return new $service(...$parameters);
79
            }
80
        );
81
    }
82
}
83