DefinitionAggregate::addAlias()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 5
cts 5
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 2
1
<?php declare(strict_types=1);
2
3
namespace Phact\Container\Definition;
4
5
use Phact\Container\Exceptions\DuplicateNameException;
6
use Phact\Container\Exceptions\NotFoundException;
7
8
class DefinitionAggregate implements DefinitionAggregateInterface
9
{
10
    /**
11
     * @var Definition[]
12
     */
13
    protected $definitions = [];
14
15
    /**
16
     * @var array
17
     */
18
    protected $references = [];
19
20
    /**
21
     * @var array
22
     */
23
    protected $aliases = [];
24
25
    /**
26
     * @var bool
27
     */
28
    protected $analyzeReferences = true;
29
30
    /**
31
     * Set analyze all added classes with class_parents and class_implements and create references.
32
     * When you add Child class to container and try get object by Parent class you will get Child class object
33
     * that described in container.
34
     *
35
     * @param bool $analyzeReferences
36
     */
37 1
    public function setAnalyzeReferences(bool $analyzeReferences): void
38
    {
39 1
        $this->analyzeReferences = $analyzeReferences;
40 1
    }
41
42
    /**
43
     * {@inheritDoc}
44
     */
45 22
    public function addDefinition(string $name, DefinitionInterface $definition): DefinitionInterface
46
    {
47 22
        if (isset($this->definitions[$name])) {
48 2
            throw new DuplicateNameException("Definition with name {$name} already exists.");
49
        }
50 22
        $this->definitions[$name] = $definition;
51 22
        if ($this->analyzeReferences) {
52 21
            $this->addReferences($name, $definition->getClass());
53
        }
54 22
        $this->addAliases($name, $definition->getAliases());
55 22
        return $definition;
56
    }
57
58
    /**
59
     * Add references by class parents and interfaces
60
     *
61
     * @param string $name
62
     * @param string $class
63
     */
64 21
    protected function addReferences(string $name, string $class): void
65
    {
66 21
        $this->addReference($name, $class);
67 21
        $interfaces = class_implements($class);
68 21
        foreach ($interfaces as $interface) {
69 9
            $this->addReference($name, $interface);
70
        }
71 21
        $parents = class_parents($class);
72 21
        foreach ($parents as $parent) {
73 9
            $this->addReference($name, $parent);
74
        }
75 21
    }
76
77
    /**
78
     * {@inheritDoc}
79
     */
80 21
    public function addReference(string $name, string $class): void
81
    {
82 21
        if (!isset($this->references[$class])) {
83 21
            $this->references[$class] = [];
84
        }
85 21
        $this->references[$class][] = $name;
86 21
    }
87
88
89 22
    public function addAliases(string $name, array $aliases = []): void
90
    {
91 22
        foreach ($aliases as $alias) {
92 5
            $this->addAlias($name, $alias);
93
        }
94 22
    }
95
96 5
    public function addAlias(string $name, string $alias): void
97
    {
98 5
        if (!isset($this->aliases[$alias])) {
99 5
            $this->aliases[$alias] = [];
100
        }
101 5
        $this->aliases[$alias][] = $name;
102 5
    }
103
104
    /**
105
     * {@inheritDoc}
106
     */
107 11
    public function get(string $id): DefinitionInterface
108
    {
109 11
        $name = $this->findDefinitionName($id);
110 11
        if ($name === null) {
111 1
            throw new NotFoundException("Could not resolve definition by id - {$id}");
112
        }
113 10
        return $this->definitions[$name];
114
    }
115
116
    /**
117
     * {@inheritDoc}
118
     */
119 22
    public function has(string $id): bool
120
    {
121
        return (
122 22
            isset($this->definitions[$id]) ||
123 15
            isset($this->aliases[$id]) ||
124 22
            ($this->analyzeReferences && isset($this->references[$id]))
125
        );
126
    }
127
128
    /**
129
     * Find definition name by aliases, references, etc
130
     *
131
     * @param string $id
132
     * @return string
133
     * @throws NotFoundException
134
     */
135 11
    public function resolveDefinitionName(string $id): string
136
    {
137 11
        $name = $this->findDefinitionName($id);
138 11
        if ($name === null) {
139 1
            throw new NotFoundException("Could not resolve definition by id - {$id}");
140
        }
141 10
        return $name;
142
    }
143
144
    /**
145
     * @param $id
146
     * @return string|null
147
     */
148 14
    protected function findDefinitionName($id): ?string
149
    {
150 14
        if (!isset($this->definitions[$id])) {
151 10
            if (isset($this->aliases[$id])) {
152 3
                $id = reset($this->aliases[$id]);
153
            }
154 10
            if ($this->analyzeReferences && isset($this->references[$id])) {
155 5
                $id = reset($this->references[$id]);
156
            }
157
        }
158 14
        if (!isset($this->definitions[$id])) {
159 2
            return null;
160
        }
161 12
        return $id;
162
    }
163
}
164