Passed
Pull Request — master (#274)
by Dmitriy
02:14
created

CompositeContainer::detach()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 3
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Di;
6
7
use InvalidArgumentException;
8
use Psr\Container\ContainerInterface;
9
use function get_class;
10
use function gettype;
11
use function is_object;
12
use function is_string;
13
14
/**
15
 * A composite container for use with containers that support the delegate lookup feature.
16
 */
17
final class CompositeContainer implements ContainerInterface
18
{
19
    /**
20
     * Containers to look into starting from the beginning of the array.
21
     *
22
     * @var ContainerInterface[] The list of containers.
23
     */
24
    private array $containers = [];
25
26 25
    public function get($id)
27
    {
28
        /** @psalm-suppress TypeDoesNotContainType */
29 25
        if (!is_string($id)) {
30
            throw new InvalidArgumentException("Id must be a string, {$this->getVariableType($id)} given.");
31
        }
32
33 25
        if ($id === StateResetter::class) {
34 2
            $resetters = [];
35 2
            foreach ($this->containers as $container) {
36 2
                if ($container->has(StateResetter::class)) {
37 2
                    $resetters[] = $container->get(StateResetter::class);
38
                }
39
            }
40 2
            $stateResetter = new StateResetter($this);
41 2
            $stateResetter->setResetters($resetters);
42
43 2
            return $stateResetter;
44
        }
45
46 25
        if ($this->isTagAlias($id)) {
47 2
            $tags = [];
48 2
            foreach ($this->containers as $container) {
49 2
                if (!$container instanceof Container) {
50
                    continue;
51
                }
52 2
                if ($container->has($id)) {
53 2
                    $tags = array_merge($container->get($id), $tags);
0 ignored issues
show
Bug introduced by
It seems like $container->get($id) can also be of type object; however, parameter $arrays of array_merge() does only seem to accept array, 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

53
                    $tags = array_merge(/** @scrutinizer ignore-type */ $container->get($id), $tags);
Loading history...
54
                }
55
            }
56
57 2
            return $tags;
58
        }
59
60 23
        foreach ($this->containers as $container) {
61 23
            if ($container->has($id)) {
62 20
                return $container->get($id);
63
            }
64
        }
65
66 5
        if ($this->containers !== []) {
67 3
            $this->containers[0]->get($id);
68
        }
69
70 2
        throw new NotFoundException($id);
71
    }
72
73 19
    public function has($id): bool
74
    {
75 19
        foreach ($this->containers as $container) {
76 5
            if ($container->has($id)) {
77 5
                return true;
78
            }
79
        }
80 14
        return false;
81
    }
82
83
    /**
84
     * Attaches a container to the composite container.
85
     *
86
     * @param ContainerInterface $container
87
     */
88 27
    public function attach(ContainerInterface $container): void
89
    {
90 27
        $this->containers[] = $container;
91 27
    }
92
93
    /**
94
     * Removes a container from the list of containers.
95
     *
96
     * @param ContainerInterface $container
97
     */
98 2
    public function detach(ContainerInterface $container): void
99
    {
100 2
        foreach ($this->containers as $i => $c) {
101 2
            if ($container === $c) {
102 2
                unset($this->containers[$i]);
103
            }
104
        }
105 2
    }
106
107 25
    private function isTagAlias(string $id): bool
108
    {
109 25
        return strncmp($id, 'tag@', 4) === 0;
110
    }
111
112
    /**
113
     * @param mixed $variable
114
     */
115
    private function getVariableType($variable): string
116
    {
117
        return is_object($variable) ? get_class($variable) : gettype($variable);
118
    }
119
}
120