Passed
Push — master ( 4f2252...ebbd35 )
by Koldo
02:07
created

ContainerConfig::lazyLoadServices()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Antidot\Container\Config;
6
7
use Antidot\Container\ContainerDelegatorFactory;
8
use ArrayObject;
9
use Aura\Di\Container;
10
use Aura\Di\ContainerConfigInterface;
11
12
use function dump;
13
use function is_array;
14
15
/**
16
 * Configuration for the Aura.Di container.
17
 * This class provides functionality for the following service types:
18
 * - Aliases
19
 * - Delegators
20
 * - Factories
21
 * - Invokable classes
22
 * - Services (known instances)
23
 * - conditionals
24
 */
25
final class ContainerConfig implements ContainerConfigInterface
26
{
27
    private $config;
28
29 9
    public function __construct(array $config)
30
    {
31 9
        $this->config = $config;
32 9
    }
33
34 8
    public function define(Container $container)
35
    {
36 8
        $container->set('config', new ArrayObject($this->config, ArrayObject::ARRAY_AS_PROPS));
37 8
        if (empty($this->config['dependencies'])) {
38 1
            return null;
39
        }
40 7
        $dependencies = $this->config['dependencies'];
41 7
        if (isset($dependencies['delegators'])) {
42
            $dependencies = $this->marshalDelegators($container, $dependencies);
43
        }
44 7
        $this->lazyLoadServices($container, $dependencies);
45 7
        $this->lazyLoadFactories($container, $dependencies);
46 7
        $this->lazyLoadConditionals($container, $dependencies);
47 7
        $this->lazyLoadInvokables($container, $dependencies);
48 7
        $this->lazyLoadAliases($container, $dependencies);
49 7
    }
50
51 1
    public function modify(Container $container)
52
    {
53 1
    }
54
55
    private function marshalDelegators(Container $container, array $dependencies): array
56
    {
57
        foreach ($dependencies['delegators'] as $service => $delegatorNames) {
58
            $factory = null;
59
            if (isset($dependencies['services'][$service])) {
60
                // Marshal from service
61
                $instance = $dependencies['services'][$service];
62
                $factory = function () use ($instance) {
63
                    return $instance;
64
                };
65
                unset($dependencies['service'][$service]);
66
            }
67
            if (isset($dependencies['factories'][$service])) {
68
                // Marshal from factory
69
                $serviceFactory = $dependencies['factories'][$service];
70
                $factory = function () use ($service, $serviceFactory, $container) {
71
                    $aService = new $serviceFactory();
72
73
                    return \is_callable($serviceFactory)
74
                        ? $serviceFactory($container, $service)
75
                        : $aService($container, $service);
76
                };
77
                unset($dependencies['factories'][$service]);
78
            }
79
            if (isset($dependencies['invokables'][$service])) {
80
                // Marshal from invokable
81
                $class = $dependencies['invokables'][$service];
82
                $factory = function () use ($class) {
83
                    return new $class();
84
                };
85
                unset($dependencies['invokables'][$service]);
86
            }
87
            if (!\is_callable($factory)) {
88
                continue;
89
            }
90
            $delegatorFactory = 'AuraDelegatorFactory::'.$service;
91
            $container->set($delegatorFactory, static function () use ($delegatorNames, $factory) {
92
                return new ContainerDelegatorFactory($delegatorNames, $factory);
0 ignored issues
show
Bug introduced by
It seems like $factory can also be of type null; however, parameter $factory of Antidot\Container\Contai...rFactory::__construct() does only seem to accept callable, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

92
                return new ContainerDelegatorFactory($delegatorNames, /** @scrutinizer ignore-type */ $factory);
Loading history...
93
            });
94
            $container->set(
95
                $service,
96
                $container->lazyGetCall($delegatorFactory, 'build', $container, $service)
97
            );
98
            $container->types[$service] = $container->lazyGet($service);
99
        }
100
101
        return $dependencies;
102
    }
103
104 3
    private function lazyLoad(Container $container, array $dependencies, string $type): void
105
    {
106 3
        foreach ($dependencies[$type] as $service => $class) {
107 3
            $container->set($service, $container->lazyNew($class));
108 3
            $container->types[$service] = $container->lazyGet($service);
109
        }
110 3
    }
111
112 7
    private function lazyLoadFactories(Container $container, array $dependencies): void
113
    {
114 7
        if (empty($dependencies['factories'])) {
115 5
            return;
116
        }
117 2
        foreach ($dependencies['factories'] as $service => $factory) {
118 2
            if (is_array($factory)) {
119 1
                $container->set($factory[0], $container->lazyNew($factory[0]));
120 1
                $container->set($service, $container->lazyGetCall(
121 1
                    $factory[0],
122 1
                    '__invoke',
123 1
                    $container,
124 1
                    $factory[1]
125
                ));
126
            } else {
127 1
                $container->set($factory, $container->lazyNew($factory));
128 1
                $container->set($service, $container->lazyGetCall($factory, '__invoke', $container));
129
            }
130 2
            $container->types[$service] = $container->lazyGet($service);
131
        }
132 2
    }
133
134 7
    private function lazyLoadConditionals(Container $container, array $dependencies): void
135
    {
136 7
        if (empty($dependencies['conditionals'])) {
137 5
            return;
138
        }
139
140 2
        foreach ($dependencies['conditionals'] as $id => $conditional) {
141 2
            $params = [];
142 2
            foreach ($conditional['arguments'] as $type => $implementation) {
143 2
                if (is_array($implementation)) {
144
                    $params[$type] = $implementation;
145
                    $container->params[$id][$type] = $params[$type];
146
                    $container->set($id, $container->lazyNew($conditional['class'], $params));
147
                    $container->types[$id] = $container->lazyGet($id);
148
                    continue;
149
                }
150
151 2
                if (!$container->has($implementation)) {
152 1
                    $container->set($implementation, $container->lazyNew($implementation));
153 1
                    $container->types[$implementation] = $container->lazyGet($implementation);
154
                }
155 2
                $params[$type] = $container->lazyGet($implementation);
156 2
                $container->params[$id][$type] = $params[$type];
157
            }
158 2
            if (!$container->has($id)) {
159 1
                $container->set($id, $container->lazyNew($conditional['class'], $params));
160 2
                $container->types[$id] = $container->lazyGet($id);
161
            }
162
        }
163 2
    }
164
165 7
    private function lazyLoadInvokables(Container $container, array $dependencies): void
166
    {
167 7
        if (empty($dependencies['invokables'])) {
168 6
            return;
169
        }
170
171 1
        $this->lazyLoad($container, $dependencies, 'invokables');
172 1
    }
173
174 7
    private function lazyLoadAliases(Container $container, array $dependencies): void
175
    {
176 7
        if (empty($dependencies['aliases'])) {
177 6
            return;
178
        }
179
180 1
        $this->lazyLoad($container, $dependencies, 'aliases');
181 1
    }
182
183 7
    private function lazyLoadServices(Container $container, array $dependencies): void
184
    {
185 7
        if (empty($dependencies['services'])) {
186 6
            return;
187
        }
188
189 1
        $this->lazyLoad($container, $dependencies, 'services');
190 1
    }
191
}
192