Passed
Pull Request — master (#86)
by Aleksei
02:24
created

BaseProviderCollector::withConfig()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 5
ccs 4
cts 4
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Cycle\Schema\Provider\Support;
6
7
use Psr\Container\ContainerInterface;
8
use RuntimeException;
9
use SplFixedArray;
10
use Yiisoft\Yii\Cycle\Exception\CumulativeException;
11
use Yiisoft\Yii\Cycle\Schema\SchemaProviderInterface;
12
13
abstract class BaseProviderCollector implements SchemaProviderInterface
14
{
15
    protected const IS_SEQUENCE_PIPELINE = true;
16
17
    /** @var SplFixedArray<DeferredSchemaProviderDecorator>|null */
18
    protected ?SplFixedArray $providers = null;
19
    private ContainerInterface $container;
20
21 23
    public function __construct(ContainerInterface $container)
22
    {
23 23
        $this->container = $container;
24 23
    }
25
26
    /**
27
     * @return $this
28
     *
29
     * @psalm-immutable
30
     */
31 21
    public function withConfig(array $config): self
32
    {
33 21
        $new = clone $this;
34 21
        $new->providers = $this->createSequence($new->container, $config);
35 21
        return $new;
36
    }
37
38
    public function read(?SchemaProviderInterface $nextProvider = null): ?array
39
    {
40
        if ($this->providers === null) {
41
            throw new RuntimeException(self::class . ' is not configured.');
42
        }
43
        if ($this->providers->count() === 0) {
44
            return $nextProvider === null ? null : $nextProvider->read();
45
        }
46
        $this->providers->rewind();
47
        return $this->providers->current()->read($nextProvider);
48
    }
49
50 5
    public function clear(): bool
51
    {
52 5
        if ($this->providers === null) {
53 1
            throw new RuntimeException(self::class . ' is not configured.');
54
        }
55 4
        $exceptions = [];
56 4
        $result = false;
57 4
        foreach ($this->providers as $provider) {
58
            try {
59 3
                $result = $provider->clear() || $result;
60 1
            } catch (\Throwable $e) {
61 1
                $exceptions[] = $e;
62
            }
63
        }
64 4
        if (count($exceptions)) {
65 1
            throw new CumulativeException(...$exceptions);
66
        }
67 3
        return $result;
68
    }
69
70 21
    protected function createSequence(ContainerInterface $container, array $providers): SplFixedArray
71
    {
72 21
        $size = count($providers);
73 21
        $stack = new SplFixedArray($size);
74 21
        $nextProvider = null;
75 21
        foreach (array_reverse($providers) as $key => $definition) {
76 17
            $config = [];
77 17
            if (is_array($definition)) {
78 5
                if (is_string($key)) {
79 2
                    $config = $definition;
80 2
                    $definition = $key;
81
                } else {
82 3
                    $config = $definition[1] ?? [];
83 3
                    $definition = $definition[0];
84
                }
85
            }
86 17
            $nextProvider = (new DeferredSchemaProviderDecorator(
87 17
                $container,
88
                $definition,
89 17
                static::IS_SEQUENCE_PIPELINE ? $nextProvider : null
90 17
            ))->withConfig($config);
91 17
            $stack[--$size] = $nextProvider;
92
        }
93 21
        return $stack;
94
    }
95
}
96