Passed
Push — main ( 432d45...7922c5 )
by Sammy
01:40
created

Prober::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 2 Features 0
Metric Value
eloc 4
c 2
b 2
f 0
dl 0
loc 7
rs 10
cc 1
nc 1
nop 2
1
<?php
2
3
namespace HexMakina\LeMarchand;
4
5
use Psr\Container\ContainerInterface;
6
7
class Prober
8
{
9
    private static array $cascade_cache = [];
10
11
    private ContainerInterface $container;
12
    private Configuration $configuration;
13
    private Factory $factory;
14
    private array $cascade;
15
16
    public function __construct(Configuration $conf, array $cascade=[])
17
    {
18
        $this->configuration = $conf;
19
        $this->cascade = $cascade;
20
21
        $this->container = $this->configuration->container();
22
        $this->factory = new Factory($this->container);
23
    }
24
25
    public function probeSettings(array $settings)
26
    {
27
        if (!$this->configuration->isSettings()) {
28
            return null;
29
        }
30
31
        //dot based hierarchy, parse and climb
32
        foreach (explode('.', $this->configuration->id()) as $k) {
33
            if (!isset($settings[$k])) {
34
                throw new NotFoundException($this->configuration->id());
35
            }
36
            $settings = $settings[$k];
37
        }
38
39
        return $settings;
40
    }
41
42
    public function probeClasses(array $construction_args = []): ?object
43
    {
44
        return $this->configuration->isExistingClass()
45
          ? $this->factory->serve($this->configuration->id(), $construction_args)
46
          : null;
47
    }
48
49
    public function probeInterface(array $wires): ?object
50
    {
51
        if (!$this->configuration->isInterface()) {
52
            return null;
53
        }
54
55
        if (!isset($wires[$this->configuration->id()])) {
56
            throw new NotFoundException($this->configuration->id());
57
        }
58
59
        $wire = $wires[$this->configuration->id()];
60
61
        // interface + constructor params
62
63
        if (is_array($wire)) { // hasEmbeddedConstructorParameters, [0] is class, then args
64
            $class = array_shift($wire);
65
            $args = $wire;
66
        } else { // simple instantiation
67
            $class = $wire;
68
            $args = null;
69
        }
70
71
        return $this->factory->serve($class, $args);
72
    }
73
74
    public function probeCascade()
75
    {
76
        $class_name = $this->configuration->rxModelOrController();
77
78
        if (is_null($class_name)) {
79
            return null;
80
        }
81
82
        $class_name = $this->cascadeNamespace($class_name);
83
84
        if ($this->configuration->hasClassNameModifier()) {
85
            $ret = $class_name;
86
        } elseif ($this->configuration->hasNewInstanceModifier()) {
87
            $ret = $this->factory->build($class_name, []);
88
        } else {
89
            $ret = $this->factory->serve($class_name, []);
90
        }
91
92
        return $ret;
93
    }
94
95
96
    private function cascadeNamespace(string $class_name) : string
97
    {
98
        if (isset($this::$cascade_cache[$class_name])) {
99
            return $this::$cascade_cache[$class_name];
100
        }
101
102
        // not fully namespaced, lets cascade
103
        foreach ($this->cascade as $ns) {
104
            if (class_exists($fully_namespaced = $ns . $class_name)) {
105
106
                $this::$cascade_cache[$class_name] = $fully_namespaced;
107
108
                return $fully_namespaced;
109
            }
110
        }
111
112
        throw new NotFoundException($class_name);
113
    }
114
}
115