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

SchemaProviderDispatcher::readSchema()   A

Complexity

Conditions 6
Paths 3

Size

Total Lines 30
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 15
c 0
b 0
f 0
nc 3
nop 0
dl 0
loc 30
rs 9.2222
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
        $toClear = [];
56
        $isWritableLast = false;
57
        $this->walkProviders(static function (SchemaProviderInterface $provider) use (&$toClear, &$isWritableLast) {
58
            $isWritableLast = $provider->isWritable();
59
            if ($isWritableLast) {
60
                $toClear[] = $provider;
61
            }
62
        });
63
        if ($isWritableLast) {
64
            array_pop($toClear);
65
        }
66
        array_walk($toClear, static function (SchemaProviderInterface $provider) {
67
            $provider->clear();
68
        });
69
    }
70
71
    private function walkProviders(\Closure $closure)
72
    {
73
        foreach ($this->providers as $key => &$provider) {
74
            // Providers resolving
75
            if (is_string($provider)) {
76
                $provider = $this->container->get($provider);
77
            }
78
            // If Provider defined as ClassName => ConfigArray
79
            if (is_array($provider) && is_string($key)) {
80
                $provider = $this->container->get($key)->withConfig($provider);
81
            }
82
83
            if (!$provider instanceof SchemaProviderInterface) {
84
                throw new \RuntimeException('Provider should be instance of SchemaProviderInterface.');
85
            }
86
            if ($closure($provider) === false) {
87
                break;
88
            }
89
        }
90
    }
91
92
}
93