Passed
Push — master ( cfe928...9076e1 )
by Alexander
10:06 queued 08:36
created

Factory::setMultiple()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
nc 2
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 2
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Factory;
6
7
use Psr\Container\ContainerInterface;
8
use Yiisoft\Factory\Definitions\DefinitionInterface;
9
use Yiisoft\Factory\Definitions\Normalizer;
10
use Yiisoft\Factory\Definitions\ArrayDefinition;
11
use Yiisoft\Factory\Exceptions\InvalidConfigException;
12
use Yiisoft\Factory\Exceptions\NotInstantiableException;
13
14
class Factory implements FactoryInterface
15
{
16
    /**
17
     * @var ContainerInterface parent container
18
     */
19
    private $container;
20
21
    /**
22
     * @var DefinitionInterface[] object definitions indexed by their types
23
     */
24
    private $definitions = [];
25
26
    /**
27
     * Factory constructor.
28
     *
29
     * @param array $definitions
30
     * @param ContainerInterface $container
31
     * @throws InvalidConfigException
32
     * @throws NotInstantiableException
33
     */
34 42
    public function __construct(ContainerInterface $container = null, array $definitions = [])
35
    {
36 42
        $this->container = $container;
37 42
        $this->setMultiple($definitions);
38 42
    }
39
40 31
    public function create($config, array $params = [])
41
    {
42 31
        $definition = Normalizer::normalize($config, null, $params);
43 31
        if ($definition instanceof ArrayDefinition && $this->has($definition->getClass())) {
44 4
            $definition = $this->merge($this->getDefinition($definition->getClass()), $definition);
45
        }
46
47 31
        if ($definition instanceof ArrayDefinition) {
48 12
            return $definition->resolve($this->container ?? $this);
49
        }
50
51 19
        return $definition->resolve($this);
52
    }
53
54 4
    private function merge(DefinitionInterface $one, DefinitionInterface $two): DefinitionInterface
55
    {
56 4
        return $one instanceof ArrayDefinition ? $one->merge($two) : $two;
57
    }
58
59 32
    public function get($id)
60
    {
61 32
        $definition = $this->getDefinition($id);
62 32
        if ($definition instanceof ArrayDefinition) {
63 30
            return $definition->resolve($this->container ?? $this);
64
        }
65
66 10
        return $definition->resolve($this);
67
    }
68
69 36
    public function getDefinition($id): DefinitionInterface
70
    {
71 36
        if ($this->has($id)) {
72 19
            return $this->definitions[$id];
73
        }
74
75
        // XXX out of nowhere solution, without it infinite loop
76 25
        if (\is_string($id)) {
77 25
            return new ArrayDefinition($id);
78
        }
79
80
        return Normalizer::normalize($id);
81
    }
82
83
    /**
84
     * Sets a definition to the factory.
85
     * @param string $id
86
     * @param mixed $definition
87
     * @throws InvalidConfigException
88
     * @see `Normalizer::normalize()`
89
     */
90 21
    public function set(string $id, $definition): void
91
    {
92 21
        $this->definitions[$id] = Normalizer::normalize($definition, $id);
93 21
    }
94
95
    /**
96
     * Sets multiple definitions at once.
97
     * @param array $definitions definitions indexed by their ids
98
     * @throws InvalidConfigException
99
     */
100 42
    public function setMultiple(array $definitions): void
101
    {
102 42
        foreach ($definitions as $id => $definition) {
103 19
            $this->set($id, $definition);
104
        }
105 42
    }
106
107
    /**
108
     * Returns a value indicating whether the container has the definition of the specified name.
109
     * @param string $id class name, interface name or alias name
110
     * @return bool whether the container is able to provide instance of class specified.
111
     * @see set()
112
     */
113 40
    public function has($id): bool
114
    {
115 40
        return isset($this->definitions[$id]);
116
    }
117
}
118