Completed
Push — master ( 3fd1d6...13dba5 )
by Jasper
11:20 queued 16s
created

EncryptedFilesystemAdapter::read()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 6
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Swis\Flysystem\Encrypted;
6
7
use Illuminate\Contracts\Encryption\DecryptException;
8
use Illuminate\Contracts\Encryption\Encrypter;
9
use Illuminate\Contracts\Encryption\EncryptException;
10
use Illuminate\Support\Traits\ForwardsCalls;
11
use League\Flysystem\FileAttributes;
12
use League\Flysystem\FilesystemAdapter;
13
use League\Flysystem\Config;
14
use League\Flysystem\UnableToReadFile;
15
use League\Flysystem\UnableToRetrieveMetadata;
16
use League\Flysystem\UnableToWriteFile;
17
use League\MimeTypeDetection\ExtensionMimeTypeDetector;
18
use League\MimeTypeDetection\MimeTypeDetector;
19
20
class EncryptedFilesystemAdapter implements FilesystemAdapter
21
{
22
    use ForwardsCalls;
23
24
    /**
25
     * @var \League\Flysystem\FilesystemAdapter
26
     */
27
    private $adapter;
28
29
    /**
30
     * @var \Illuminate\Contracts\Encryption\Encrypter
31
     */
32
    private $encrypter;
33
34
    /**
35
     * @var \League\MimeTypeDetection\MimeTypeDetector
36
     */
37
    private $mimeTypeDetector;
38
39
    /**
40
     * @param \League\Flysystem\FilesystemAdapter $adapter
41
     * @param \Illuminate\Contracts\Encryption\Encrypter $encrypter
42
     * @param \League\MimeTypeDetection\MimeTypeDetector|null $mimeTypeDetector
43
     */
44
    public function __construct(FilesystemAdapter $adapter, Encrypter $encrypter, MimeTypeDetector $mimeTypeDetector = null)
45
    {
46
        $this->adapter = $adapter;
47
        $this->encrypter = $encrypter;
48
        $this->mimeTypeDetector = $mimeTypeDetector ?: new ExtensionMimeTypeDetector();
49
    }
50
51
    /**
52
     * @inheritDoc
53
     */
54
    public function fileExists(string $path): bool
55
    {
56
        return $this->adapter->fileExists($path);
57
    }
58
59
    /**
60
     * @inheritDoc
61
     */
62
    public function write(string $path, string $contents, Config $config): void
63
    {
64
        try {
65
            $this->adapter->write($path, $this->encrypter->encrypt($contents), $config);
66
        } catch (EncryptException $exception) {
67
            throw UnableToWriteFile::atLocation($path, $exception->getMessage(), $exception);
68
        }
69
    }
70
71
    /**
72
     * @inheritDoc
73
     */
74
    public function writeStream(string $path, $contents, Config $config): void
75
    {
76
        $this->write($path, stream_get_contents($contents), $config);
77
    }
78
79
    /**
80
     * @inheritDoc
81
     */
82
    public function read(string $path): string
83
    {
84
        try {
85
            return $this->encrypter->decrypt($this->adapter->read($path));
86
        } catch (DecryptException $exception) {
87
            throw UnableToReadFile::fromLocation($path, $exception->getMessage(), $exception);
88
        }
89
    }
90
91
    /**
92
     * @inheritDoc
93
     */
94
    public function readStream(string $path)
95
    {
96
        $stream = tmpfile();
97
98
        if ($stream === false) {
99
            throw UnableToReadFile::fromLocation($path, 'Unable to create temporary stream.');
100
        }
101
102
        fwrite($stream, $this->read($path));
103
        fseek($stream, 0);
104
105
        return $stream;
106
    }
107
108
    /**
109
     * @inheritDoc
110
     */
111
    public function delete(string $path): void
112
    {
113
        $this->adapter->delete($path);
114
    }
115
116
    /**
117
     * @inheritDoc
118
     */
119
    public function deleteDirectory(string $path): void
120
    {
121
        $this->adapter->deleteDirectory($path);
122
    }
123
124
    /**
125
     * @inheritDoc
126
     */
127
    public function createDirectory(string $path, Config $config): void
128
    {
129
        $this->adapter->createDirectory($path, $config);
130
    }
131
132
    /**
133
     * @inheritDoc
134
     */
135
    public function setVisibility(string $path, string $visibility): void
136
    {
137
        $this->adapter->setVisibility($path, $visibility);
138
    }
139
140
    /**
141
     * @inheritDoc
142
     */
143
    public function visibility(string $path): FileAttributes
144
    {
145
        return $this->adapter->visibility($path);
146
    }
147
148
    /**
149
     * @inheritDoc
150
     */
151
    public function mimeType(string $path): FileAttributes
152
    {
153
        try {
154
            $mimeType = $this->mimeTypeDetector->detectMimeType($path, $this->read($path));
155
        } catch (UnableToReadFile $exception) {
156
            throw UnableToRetrieveMetadata::mimeType($path, $exception->getMessage(), $exception);
157
        }
158
159
        if ($mimeType === null) {
160
            throw UnableToRetrieveMetadata::mimeType($path);
161
        }
162
163
        return new FileAttributes($path, null, null, null, $mimeType);
164
    }
165
166
    /**
167
     * @inheritDoc
168
     */
169
    public function lastModified(string $path): FileAttributes
170
    {
171
        return $this->adapter->lastModified($path);
172
    }
173
174
    /**
175
     * @inheritDoc
176
     */
177
    public function fileSize(string $path): FileAttributes
178
    {
179
        try {
180
            return new FileAttributes($path, \strlen($this->read($path)));
181
        } catch (UnableToReadFile $exception) {
182
            throw UnableToRetrieveMetadata::fileSize($path, $exception->getMessage(), $exception);
183
        }
184
    }
185
186
    /**
187
     * @inheritDoc
188
     */
189
    public function listContents(string $path, bool $deep): iterable
190
    {
191
        return $this->adapter->listContents($path, $deep);
192
    }
193
194
    /**
195
     * @inheritDoc
196
     */
197
    public function move(string $source, string $destination, Config $config): void
198
    {
199
        $this->adapter->move($source, $destination, $config);
200
    }
201
202
    /**
203
     * @inheritDoc
204
     */
205
    public function copy(string $source, string $destination, Config $config): void
206
    {
207
        $this->adapter->copy($source, $destination, $config);
208
    }
209
210
    /**
211
     * Dynamically pass missing methods to the decorated adapter.
212
     *
213
     * @param string $method
214
     * @param array $parameters
215
     *
216
     * @return mixed
217
     */
218
    public function __call(string $method, array $parameters)
219
    {
220
        return $this->forwardCallTo($this->adapter, $method, $parameters);
221
    }
222
}
223