Passed
Push — master ( 889c90...5b2f85 )
by Koldo
02:25
created

Builder::assertValidAlias()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 4
c 1
b 0
f 0
dl 0
loc 6
ccs 0
cts 5
cp 0
rs 10
cc 2
nc 2
nop 2
crap 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Antidot\Container;
6
7
use InvalidArgumentException;
8
use Psr\Container\ContainerInterface;
9
use ReflectionMethod;
10
11
use function array_key_exists;
12
use function array_merge;
13
use function sprintf;
14
15
class Builder
16
{
17
    /**
18
     * @param array<mixed> $dependencies
19
     */
20 10
    public static function build(array $dependencies, bool $autowire = false): ContainerInterface
21
    {
22 10
        $self = new self();
23
24 10
        return new Container(
25 10
            $self->parseConfigFor($dependencies),
26
            $autowire
27
        );
28
    }
29
30
    /**
31
     * @param array<mixed> $dependencies
32
     */
33 10
    private function parseConfigFor(array $dependencies): ContainerConfig
34
    {
35
        $containerConfig = [
36 10
            'config' => $dependencies,
37
            'parameters' => [],
38 10
            'delegators' => $dependencies['delegators'] ?? [],
39
        ];
40
41 10
        foreach ($dependencies['factories'] ?? [] as $name => $factory) {
42 3
            $containerConfig[$name] = static function (ContainerInterface $container) use ($factory) {
43 3
                if (is_array($factory)) {
44 1
                    $class = array_shift($factory);
45 1
                    $instance = new $class();
46 1
                    $method = new ReflectionMethod($class, '__invoke');
47 1
                    return $method->invokeArgs($instance, array_merge([$container], $factory));
48
                }
49
50 2
                if (is_callable($factory)) {
51 1
                    return $factory($container);
52
                }
53
54 1
                if (class_exists($factory)) {
55 1
                    return (new $factory())($container);
56
                }
57
58
                throw new InvalidArgumentException('Invalid factory type given.');
59
            };
60
        }
61
62 10
        $services = array_merge(
63 10
            $dependencies['services'] ?? [],
64 10
            $dependencies['dependencies']['invokables'] ?? []
65
        );
66
67 10
        foreach ($services as $name => $service) {
68 6
            $this->assertValidService($service);
69 3
            if (is_array($service)) {
70 1
                $containerConfig['parameters'][$name] = $service['arguments'] ?? [];
71 1
                $containerConfig[$name] = $service['class'];
72
            }
73
74 3
            if (is_string($service)) {
75 2
                $containerConfig[$name] = $service;
76
            }
77
        }
78
79 7
        $aliases = array_merge(
80 7
            $dependencies['aliases'] ?? [],
81 7
            $dependencies['dependencies']['aliases'] ?? []
82
        );
83 7
        foreach ($aliases as $alias => $service) {
84
            $this->assertValidAlias($service, $containerConfig);
85
            $containerConfig[$alias] = $service;
86
        }
87
88 7
        return new ContainerConfig($containerConfig);
89
    }
90
91
    /**
92
     * @param mixed $service
93
     */
94 6
    private function assertValidService($service): void
95
    {
96 6
        if (is_array($service)) {
97 3
            if (false === array_key_exists('class', $service)) {
98 1
                throw new InvalidArgumentException(
99 1
                    'Invalid Container Configuration, "class" parameter is required for configurable dependencies.'
100
                );
101
            }
102
103 2
            $service = $service['class'];
104
        }
105
106 5
        if (false === is_string($service)) {
107 2
            throw new InvalidArgumentException(
108
                'Invalid Container Configuration, Service "class", Simple or autowired dependencies must have'
109 2
                . ' a string value.'
110
            );
111
        }
112 3
    }
113
114
    /**
115
     * @param string $service
116
     * @param array<string, string> $containerConfig
117
     */
118
    private function assertValidAlias(string $service, array $containerConfig): void
119
    {
120
        if (false === array_key_exists($service, $containerConfig)) {
121
            throw new InvalidArgumentException(sprintf(
122
                'Invalid Alias "%s" given, be sure that the service already exists.',
123
                $service
124
            ));
125
        }
126
    }
127
}
128