Container::initializeService()   A
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 24
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 13
c 1
b 0
f 0
nc 5
nop 1
dl 0
loc 24
ccs 14
cts 14
cp 1
crap 5
rs 9.5222
1
<?php
2
3
/*
4
 *  This file is part of the Micro framework package.
5
 *
6
 *  (c) Stanislau Komar <[email protected]>
7
 *
8
 *  For the full copyright and license information, please view the LICENSE
9
 *  file that was distributed with this source code.
10
 */
11
12
namespace Micro\Component\DependencyInjection;
13
14
use Micro\Component\DependencyInjection\Exception\ServiceNotRegisteredException;
15
use Micro\Component\DependencyInjection\Exception\ServiceRegistrationException;
16
use Psr\Container\ContainerInterface;
17
18
/**
19
 * @author Stanislau Komar <[email protected]>
20
 */
21
class Container implements ContainerInterface, ContainerRegistryInterface, ContainerDecoratorInterface
22
{
23
    /**
24
     * @var array<class-string, mixed>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<class-string, mixed> at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in array<class-string, mixed>.
Loading history...
25
     */
26
    private array $services = [];
27
28
    /**
29
     * @var array<class-string, callable(Container): object>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<class-string, callable(Container): object> at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in array<class-string, callable(Container): object>.
Loading history...
30
     */
31
    private array $servicesRaw = [];
32
33
    /**
34
     * @var array<class-string, array<int, array<callable(object, Container): object>>>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<class-string, arra..., Container): object>>> at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in array<class-string, array<int, array<callable(object, Container): object>>>.
Loading history...
35
     */
36
    private array $decorators = [];
37
38
    /**
39
     * @psalm-suppress MoreSpecificImplementedParamType
40
     * @psalm-suppress MixedPropertyTypeCoercion
41
     *
42
     * @template T of object
43
     *
44
     * @param class-string<T> $id
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<T> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<T>.
Loading history...
45
     *
46
     * @psalm-return T
47
     */
48 5
    public function get(string $id): object
49
    {
50 5
        if (!empty($this->services[$id])) {
51 1
            return $this->services[$id];
52
        }
53
54 5
        $this->initializeService($id);
55
56 3
        return $this->services[$id];
57
    }
58
59
    /**
60
     * @param class-string $id
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string.
Loading history...
61
     *
62
     * @psalm-suppress MoreSpecificImplementedParamType
63
     */
64 5
    public function has(string $id): bool
65
    {
66 5
        return !empty($this->servicesRaw[$id]) || !empty($this->services[$id]);
67
    }
68
69 5
    public function register(string $id, callable $service, bool $force = false): void
70
    {
71 5
        if ($this->has($id) && !$force) {
72 1
            throw new ServiceRegistrationException(sprintf('Service "%s" already registered', $id));
73
        }
74
75 5
        $this->servicesRaw[$id] = $service;
76
    }
77
78
    /**
79
     * @psalm-suppress InvalidPropertyAssignmentValue
80
     */
81 2
    public function decorate(string $id, callable $service, int $priority = 0): void
82
    {
83 2
        if (!\array_key_exists($id, $this->decorators)) {
84 2
            $this->decorators[$id] = [];
85
        }
86 2
        $this->decorators[$id][$priority][] = $service;
87
    }
88
89
    /**
90
     * @template T of Object
91
     *
92
     * @param class-string<T> $serviceId
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<T> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<T>.
Loading history...
93
     */
94 5
    protected function initializeService(string $serviceId): void
95
    {
96 5
        if (empty($this->servicesRaw[$serviceId])) {
97 2
            throw new ServiceNotRegisteredException($serviceId);
98
        }
99
100 3
        $raw = $this->servicesRaw[$serviceId];
101 3
        $service = $raw($this);
102 3
        $this->services[$serviceId] = $service;
103
104 3
        if (!\array_key_exists($serviceId, $this->decorators)) {
105 1
            return;
106
        }
107
108 2
        $decoratorsByPriority = $this->decorators[$serviceId];
109 2
        krsort($decoratorsByPriority);
110
111 2
        foreach ($decoratorsByPriority as $decorators) {
112 2
            foreach ($decorators as $decorator) {
113 2
                $this->services[$serviceId] = $decorator($this->services[$serviceId], $this);
114
            }
115
        }
116
117 2
        unset($this->decorators[$serviceId]);
118
    }
119
}
120