FlysystemEngine   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 151
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 0
Metric Value
wmc 23
lcom 1
cbo 6
dl 0
loc 151
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 3
A getId() 0 4 1
A reset() 0 7 1
A getIterator() 0 6 2
A has() 0 4 1
A read() 0 8 2
A write() 0 14 2
A delete() 0 11 2
A clear() 0 7 2
A inTransaction() 0 4 1
A commit() 0 11 2
A guessDecoder() 0 11 4
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace hanneskod\yaysondb\Engine;
6
7
use hanneskod\yaysondb\Exception\FileNotFoundException;
8
use hanneskod\yaysondb\Exception\FileModifiedException;
9
use League\Flysystem\FilesystemInterface;
10
11
/**
12
 * Engine based on a flysystem
13
 */
14
class FlysystemEngine implements EngineInterface
15
{
16
    /**
17
     * @var string Name of source file
18
     */
19
    private $fname;
20
21
    /**
22
     * @var FilesystemInterface Filesystem where source is found
23
     */
24
    private $fsystem;
25
26
    /**
27
     * @var DecoderInterface Decoder used to encode and deconde content
28
     */
29
    private $decoder;
30
31
    /**
32
     * @var array Loaded documents
33
     */
34
    private $docs;
35
36
    /**
37
     * @var string Hash of source at last reset
38
     */
39
    private $hash;
40
41
    /**
42
     * @var bool Flag if there are un-commited changes
43
     */
44
    private $inTransaction;
45
46
    /**
47
     * @throws FileNotFoundException If fname does not exist in filesystem
48
     */
49
    public function __construct(string $fname, FilesystemInterface $fsystem, DecoderInterface $decoder = null)
50
    {
51
        if (!$fsystem->has($fname)) {
52
            throw new FileNotFoundException("Unable to read file $fname");
53
        }
54
55
        $this->fname = $fname;
56
        $this->fsystem = $fsystem;
57
        $this->decoder = $decoder ?: $this->guessDecoder();
58
        $this->reset();
59
    }
60
61
    public function getId(): string
62
    {
63
        return $this->fname;
64
    }
65
66
    public function reset()
67
    {
68
        $this->inTransaction = false;
69
        $raw = (string)$this->fsystem->read($this->fname);
70
        $this->hash = md5($raw);
71
        $this->docs = $this->decoder->decode($raw);
72
    }
73
74
    public function getIterator(): \Generator
75
    {
76
        foreach ($this->docs as $id => $doc) {
77
            yield $id => $doc;
78
        }
79
    }
80
81
    public function has(string $id): bool
82
    {
83
        return isset($this->docs[$id]);
84
    }
85
86
    public function read(string $id): array
87
    {
88
        if ($this->has($id)) {
89
            return (array)$this->docs[$id];
90
        }
91
92
        return [];
93
    }
94
95
    public function write(string $id, array $doc): string
96
    {
97
        $this->inTransaction = true;
98
99
        if ('' !== $id) {
100
            $this->docs[$id] = $doc;
101
            return $id;
102
        }
103
104
        $this->docs[] = $doc;
105
        end($this->docs);
106
107
        return (string)key($this->docs);
108
    }
109
110
    public function delete(string $id): bool
111
    {
112
        if ($this->has($id)) {
113
            $this->inTransaction = true;
114
            unset($this->docs[$id]);
115
116
            return true;
117
        }
118
119
        return false;
120
    }
121
122
    public function clear()
123
    {
124
        if (!empty($this->docs)) {
125
            $this->inTransaction = true;
126
            $this->docs = [];
127
        }
128
    }
129
130
    public function inTransaction(): bool
131
    {
132
        return $this->inTransaction;
133
    }
134
135
    /**
136
     * @throws FileModifiedException If source is out of date
137
     */
138
    public function commit()
139
    {
140
        if (md5($this->fsystem->read($this->fname)) != $this->hash) {
141
            throw new FileModifiedException('Unable to commit changes: source data has changed');
142
        }
143
144
        $raw = $this->decoder->encode($this->docs);
145
        $this->fsystem->update($this->fname, $raw);
146
        $this->hash = md5($raw);
147
        $this->inTransaction = false;
148
    }
149
150
    /**
151
     * Create a decoder based of source file mime-type
152
     */
153
    private function guessDecoder(): DecoderInterface
154
    {
155
        switch ($this->fsystem->getMimetype($this->fname)) {
156
            case 'application/x-httpd-php':
157
                return new PhpDecoder;
158
            case 'text/plain':
159
            case 'application/json':
160
            default:
161
                return new JsonDecoder;
162
        }
163
    }
164
}
165