Completed
Push — master ( 790faa...1155c9 )
by Andrey
07:17
created

ContainerBuilder::setClassFinder()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

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