Passed
Pull Request — master (#68)
by Aleksei
18:23
created

PhpFileSchemaProvider::read()   B

Complexity

Conditions 7
Paths 10

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 7.2269

Importance

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