Passed
Pull Request — master (#38)
by Aleksei
13:38
created

SchemaProviderDispatcher::walkProviders()   B

Complexity

Conditions 7
Paths 13

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 9
c 1
b 0
f 0
nc 13
nop 1
dl 0
loc 17
rs 8.8333
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Cycle\Schema;
6
7
use Psr\Container\ContainerInterface;
8
9
final class SchemaProviderDispatcher
10
{
11
    private ContainerInterface $container;
12
    /** @var string[]|SchemaProviderInterface[] */
13
    private array $providers = [];
14
15
    public function __construct(ContainerInterface $container, array $providers)
16
    {
17
        $this->container = $container;
18
        $this->providers = $providers;
19
    }
20
21
    public function readSchema(): ?array
22
    {
23
        $toWrite = new \SplStack();
24
        $schema = null;
25
26
        $this->walkProviders(static function (SchemaProviderInterface $provider) use (&$schema, $toWrite): bool {
27
            // Try to read schema
28
            if ($provider->isReadable()) {
29
                $schema = $provider->read();
30
                if ($schema !== null) {
31
                    return false;
32
                }
33
            }
34
            if ($provider->isWritable()) {
35
                $toWrite->push($provider);
36
            }
37
            return true;
38
        });
39
40
        if ($schema === null) {
41
            return null;
42
        }
43
44
        // Save schema
45
        /** @var SchemaProviderInterface $provider */
46
        foreach ($toWrite as $provider) {
47
            $provider->write($schema);
48
        }
49
50
        return $schema;
51
    }
52
53
    public function clearSchema(): void
54
    {
55
        /** @var SchemaProviderInterface[] $toClear */
56
        $toClear = [];
57
        $isWritableLast = false;
58
        $this->walkProviders(static function (SchemaProviderInterface $provider) use (&$toClear, &$isWritableLast) {
59
            $isWritableLast = $provider->isWritable();
60
            if ($isWritableLast) {
61
                $toClear[] = $provider;
62
            }
63
        });
64
        if ($isWritableLast) {
65
            array_pop($toClear);
66
        }
67
        foreach ($toClear as $provider) {
68
            $provider->clear();
69
        }
70
    }
71
72
    private function walkProviders(\Closure $closure)
73
    {
74
        foreach ($this->providers as $key => &$provider) {
75
            // Providers resolving
76
            if (is_string($provider)) {
77
                $provider = $this->container->get($provider);
78
            }
79
            // If Provider defined as ClassName => ConfigArray
80
            if (is_array($provider) && is_string($key)) {
81
                $provider = $this->container->get($key)->withConfig($provider);
82
            }
83
84
            if (!$provider instanceof SchemaProviderInterface) {
85
                throw new \RuntimeException('Provider should be instance of SchemaProviderInterface.');
86
            }
87
            if ($closure($provider) === false) {
88
                break;
89
            }
90
        }
91
    }
92
}
93