Completed
Push — master ( 1a6c14...1a0ee4 )
by Andrey
02:15
created

ContainerBuilder::buildVariadicArgs()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 6
c 0
b 0
f 0
nc 5
nop 1
dl 0
loc 10
ccs 7
cts 7
cp 1
crap 4
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Borodulin\Container;
6
7
use Borodulin\Container\Autowire\CallableItemBuilder;
8
use Borodulin\Container\Autowire\ClassItemBuilder;
9
use Borodulin\Container\Autowire\ClassNameExtractor;
10
use Borodulin\Container\Autowire\FileFinder;
11
use Borodulin\Container\Autowire\Item\AliasItem;
12
use Borodulin\Container\Autowire\Item\VariadicItem;
13
use Borodulin\Container\Autowire\ItemProvider;
14
use Psr\Container\ContainerInterface;
15
use Psr\SimpleCache\CacheInterface;
16
17
class ContainerBuilder
18
{
19
    /**
20
     * @var int
21
     */
22
    private static $builderId = 0;
23
    /**
24
     * @var FileFinder
25
     */
26
    private $fileFinder;
27
    /**
28
     * @var CacheInterface|null
29
     */
30
    private $cache;
31
    /**
32
     * @var iterable
33
     */
34
    private $config = [];
35
    /**
36
     * @var int
37
     */
38
    private $id;
39
40 15
    public function __construct()
41
    {
42 15
        $this->id = ++self::$builderId;
43 15
    }
44
45 15
    public function build(): Container
46
    {
47 15
        $cacheKey = static::class.':'.$this->id;
48
49 15
        if ($this->cache && $this->cache->has($cacheKey)) {
50 1
            $itemProvider = unserialize($this->cache->get(static::class));
51
        } else {
52 15
            $itemProvider = new ItemProvider();
53 15
            $itemProvider->addItem(ContainerInterface::class, new AliasItem(ContainerInterface::class));
54
55 15
            $this->buildConfig($itemProvider);
56
57 12
            $this->buildFiles($itemProvider);
58
59 11
            $this->buildVariadicArgs($itemProvider);
60
61 11
            if ($this->cache) {
62 1
                $this->cache->set($cacheKey, serialize($itemProvider));
63
            }
64
        }
65
66 11
        return new Container(iterator_to_array($itemProvider));
67
    }
68
69 10
    public function setConfig(iterable $config): self
70
    {
71 10
        $this->config = $config;
72
73 10
        return $this;
74
    }
75
76 1
    public function setCache(?CacheInterface $cache): self
77
    {
78 1
        $this->cache = $cache;
79
80 1
        return $this;
81
    }
82
83 6
    public function setFileFinder(FileFinder $fileFinder): self
84
    {
85 6
        $this->fileFinder = $fileFinder;
86
87 6
        return $this;
88
    }
89
90 15
    private function buildConfig(ItemProvider $itemProvider): void
91
    {
92 15
        foreach ($this->config as $id => $item) {
93 10
            if (\is_string($item)) {
94 9
                if (\is_int($id)) {
95 6
                    $itemProvider->addItem($item, (new ClassItemBuilder($itemProvider))->build($item));
96
                } else {
97 3
                    if ($itemProvider->hasItem($item)) {
98 1
                        $itemProvider->addItem($id, new AliasItem($item));
99
                    } else {
100 8
                        $itemProvider->addItem($id, new AliasItem($item, (new ClassItemBuilder($itemProvider))->build($item)));
101
                    }
102
                }
103 4
            } elseif (\is_callable($item)) {
104 3
                $id = (string) $id;
105 3
                $itemProvider->addItem($id, (new CallableItemBuilder($itemProvider))->build($item));
106
            } else {
107 1
                throw new ContainerException('Unsupported item type');
108
            }
109
        }
110 12
    }
111
112 12
    private function buildFiles(ItemProvider $itemProvider): void
113
    {
114 12
        if (null !== $this->fileFinder) {
115 6
            $classNameExtractor = new ClassNameExtractor();
116 6
            foreach ($this->fileFinder as $fileName) {
117 6
                $className = $classNameExtractor->extract($fileName);
118 6
                if (null !== $className) {
119 6
                    if (!$itemProvider->hasItem($className)) {
120 6
                        $itemProvider->addItem($className, (new ClassItemBuilder($itemProvider))->build($className));
121
                    }
122
                }
123
            }
124
        }
125 11
    }
126
127 11
    private function buildVariadicArgs(ItemProvider $itemProvider): void
128
    {
129
        /** @var VariadicItem[] $items */
130 11
        foreach ($itemProvider->getVariadicPass()->getItems() as $interface => $items) {
131 5
            $classItems = [];
132 5
            foreach ($itemProvider->findInstanceOf($interface) as $className) {
133 2
                $classItems[] = (new ClassItemBuilder($itemProvider))->build($className);
134
            }
135 5
            foreach ($items as $variadicItem) {
136 5
                $variadicItem->setArgs($classItems);
137
            }
138
        }
139 11
    }
140
}
141