Passed
Push — master ( 426d0f...05f77a )
by Koldo
02:32
created

Builder   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 81
Duplicated Lines 0 %

Test Coverage

Coverage 97.22%

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 13
eloc 38
c 1
b 0
f 1
dl 0
loc 81
ccs 35
cts 36
cp 0.9722
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A assertValidService() 0 16 4
A build() 0 7 1
B parseConfigFor() 0 42 8
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
class Builder
12
{
13
    /**
14
     * @param array<mixed> $dependencies
15
     */
16 10
    public static function build(array $dependencies, bool $autowire = false): ContainerInterface
17
    {
18 10
        $self = new self();
19
20 10
        return new Container(
21 10
            $self->parseConfigFor($dependencies),
22
            $autowire
23
        );
24
    }
25
26
    /**
27
     * @param array<mixed> $dependencies
28
     */
29 10
    private function parseConfigFor(array $dependencies): ContainerConfig
30
    {
31
        $containerConfig = [
32 10
            'config' => $dependencies,
33
            'parameters' => [],
34 10
            'delegators' => $dependencies['delegators'] ?? [],
35
        ];
36
37 10
        foreach ($dependencies['factories'] ?? [] as $name => $factory) {
38 3
            $containerConfig[$name] = static function (ContainerInterface $container) use ($factory) {
39 3
                if (is_array($factory)) {
40 1
                    $class = array_shift($factory);
41 1
                    $instance = new $class();
42 1
                    $method = new ReflectionMethod($class, '__invoke');
43 1
                    return $method->invokeArgs($instance, array_merge([$container], $factory));
44
                }
45
46 2
                if (is_callable($factory)) {
47 1
                    return $factory($container);
48
                }
49
50 1
                if (class_exists($factory)) {
51 1
                    return (new $factory())($container);
52
                }
53
54
                throw new InvalidArgumentException('Invalid factory type given.');
55
            };
56
        }
57
58 10
        foreach ($dependencies['services'] ?? [] as $name => $service) {
59 6
            $this->assertValidService($service);
60 3
            if (is_array($service)) {
61 1
                $containerConfig['parameters'][$name] = $service['arguments'] ?? [];
62 1
                $containerConfig[$name] = $service['class'];
63
            }
64
65 3
            if (is_string($service)) {
66 2
                $containerConfig[$name] = $service;
67
            }
68
        }
69
70 7
        return new ContainerConfig($containerConfig);
71
    }
72
73
    /**
74
     * @param mixed $service
75
     */
76 6
    private function assertValidService($service): void
77
    {
78 6
        if (is_array($service)) {
79 3
            if (false === array_key_exists('class', $service)) {
80 1
                throw new InvalidArgumentException(
81 1
                    'Invalid Container Configuration, "class" parameter is required for configurable dependencies.'
82
                );
83
            }
84
85 2
            $service = $service['class'];
86
        }
87
88 5
        if (false === is_string($service)) {
89 2
            throw new InvalidArgumentException(
90
                'Invalid Container Configuration, Service "class", Simple or autowired dependencies must have'
91 2
                . ' a string value.'
92
            );
93
        }
94 3
    }
95
}
96