Passed
Pull Request — master (#148)
by Rustam
12:16
created

PhpFileSchemaProvider::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
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;
6
7
use Cycle\Schema\Renderer\PhpSchemaRenderer;
8
use RuntimeException;
9
use Yiisoft\Aliases\Aliases;
10
use Yiisoft\Yii\Cycle\Schema\SchemaProviderInterface;
11
12
final class PhpFileSchemaProvider implements SchemaProviderInterface
13
{
14
    public const MODE_READ_AND_WRITE = 0;
15
    public const MODE_WRITE_ONLY = 1;
16
17
    private string $file = '';
18
    private int $mode = self::MODE_READ_AND_WRITE;
19
20
    private Aliases $aliases;
21
22 12
    public function __construct(Aliases $aliases)
23
    {
24 12
        $this->aliases = $aliases;
25
    }
26
27 10
    public function withConfig(array $config): self
28
    {
29 10
        $new = clone $this;
30
31
        // required option
32 10
        if ($this->file === '' && !array_key_exists('file', $config)) {
33 1
            throw new \InvalidArgumentException('The "file" parameter is required.');
34
        }
35 9
        $new->file = $this->aliases->get($config['file']);
36
37 9
        $new->mode = $config['mode'] ?? $this->mode;
38
39 9
        return $new;
40
    }
41
42 8
    public function read(?SchemaProviderInterface $nextProvider = null): ?array
43
    {
44 8
        if (!$this->isReadable()) {
45 4
            if ($nextProvider === null) {
46 2
                throw new RuntimeException(__CLASS__ . ' can not read schema.');
47
            }
48 2
            $schema = null;
49
        } else {
50 4
            $schema = !is_file($this->file) ? null : (include $this->file);
51
        }
52
53 6
        if ($schema !== null || $nextProvider === null) {
54 2
            return $schema;
55
        }
56
57 4
        $schema = $nextProvider->read();
58 4
        if ($schema !== null) {
59 3
            $this->write($schema);
60
        }
61 3
        return $schema;
62
    }
63
64 3
    private function write(array $schema): bool
65
    {
66 3
        if (basename($this->file) === '') {
67 1
            throw new RuntimeException('The "file" parameter must not be empty.');
68
        }
69 2
        $dirname = dirname($this->file);
70 2
        if ($dirname !== '' && !is_dir($dirname)) {
71
            mkdir($dirname, 0777, true);
72
        }
73
74 2
        $content = (new PhpSchemaRenderer())->render($schema);
75 2
        file_put_contents($this->file, $content, LOCK_EX);
76 2
        return true;
77
    }
78
79 3
    private function removeFile(): void
80
    {
81 3
        if (!file_exists($this->file)) {
82 1
            return;
83
        }
84 2
        if (!is_file($this->file)) {
85 1
            throw new RuntimeException("`$this->file` is not a file.");
86
        }
87 1
        if (!is_writable($this->file)) {
88
            throw new RuntimeException("File `$this->file` is not writeable.");
89
        }
90 1
        unlink($this->file);
91
    }
92
93 3
    public function clear(): bool
94
    {
95
        try {
96 3
            $this->removeFile();
97 1
        } catch (\Throwable $e) {
98 1
            return false;
99
        }
100 2
        return true;
101
    }
102
103 8
    private function isReadable(): bool
104
    {
105 8
        return $this->mode !== self::MODE_WRITE_ONLY;
106
    }
107
}
108