Passed
Pull Request — master (#38)
by Alexander
11:20
created

SchemaManager   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 80
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 39
c 1
b 0
f 0
dl 0
loc 80
rs 10
wmc 18

4 Methods

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