Completed
Push — master ( dbb2ee...ecee5c )
by Chris
01:31
created

MemoryAdapter::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 6
cts 6
cp 1
rs 9.9666
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
1
<?php
2
3
namespace League\Flysystem\Memory;
4
5
use League\Flysystem\Adapter\Polyfill\StreamedWritingTrait;
6
use League\Flysystem\AdapterInterface;
7
use League\Flysystem\Config;
8
use League\Flysystem\Util;
9
10
/**
11
 * An adapter that keeps the filesystem in memory.
12
 */
13
class MemoryAdapter implements AdapterInterface
14
{
15
    use StreamedWritingTrait;
16
17
    /**
18
     * The emulated filesystem.
19
     *
20
     * Start with the root directory initialized.
21
     *
22
     * @var array
23
     */
24
    protected $storage;
25
26 57
    public function __construct(Config $config = null)
27
    {
28 57
        $this->storage = [
29
            '' => [
30 57
                'type' => 'dir',
31 57
                'timestamp' => $config ? $config->get('timestamp', time()) : time(),
32 19
            ],
33
        ];
34 57
    }
35
36
    /**
37
     * @inheritdoc
38
     */
39 6
    public function copy($path, $newpath)
40
    {
41
        // Make sure all the destination sub-directories exist.
42 6
        if ( ! $this->doCreateDir(Util::dirname($newpath), new Config())) {
43 6
            return false;
44
        }
45
46 6
        $this->storage[$newpath] = $this->storage[$path];
47
48 6
        return true;
49
    }
50
51
    /**
52
     * @inheritdoc
53
     */
54 9
    public function createDir($dirname, Config $config)
55
    {
56 9
        if ( ! $this->doCreateDir($dirname, $config)) {
57 3
            return false;
58
        }
59
60 9
        return $this->getMetadata($dirname);
61
    }
62
63
    /**
64
     * @inheritdoc
65
     */
66 3
    public function delete($path)
67
    {
68 3
        if ( ! $this->hasFile($path)) {
69 3
            return false;
70
        }
71
72 3
        unset($this->storage[$path]);
73
74 3
        return true;
75
    }
76
77
    /**
78
     * @inheritdoc
79
     */
80 3
    public function deleteDir($dirname)
81
    {
82 3
        if ( ! $this->hasDirectory($dirname)) {
83 3
            return false;
84
        }
85
86 3
        foreach ($this->doListContents($dirname, true) as $path) {
87 3
            unset($this->storage[$path]);
88 1
        }
89
90 3
        unset($this->storage[$dirname]);
91
92 3
        return true;
93
    }
94
95
    /**
96
     * @inheritdoc
97
     */
98 57
    public function getMetadata($path)
99
    {
100 57
        $metadata = $this->storage[$path] + ['path' => $path];
101 57
        unset($metadata['contents']);
102
103 57
        return $metadata;
104
    }
105
106
    /**
107
     * @inheritdoc
108
     */
109 3
    public function getMimetype($path)
110
    {
111 3
        $mimetype = Util::guessMimeType($path, $this->storage[$path]['contents']);
112
113
        return [
114 3
            'mimetype' => $mimetype,
115 3
            'path' => $path,
116 1
        ];
117
    }
118
119
    /**
120
     * @inheritdoc
121
     */
122 3
    public function getSize($path)
123
    {
124 3
        return $this->getMetadata($path);
125
    }
126
127
    /**
128
     * @inheritdoc
129
     */
130 9
    public function getTimestamp($path)
131
    {
132 9
        return $this->getMetadata($path);
133
    }
134
135
    /**
136
     * @inheritdoc
137
     */
138 6
    public function getVisibility($path)
139
    {
140 6
        return $this->getMetadata($path);
141
    }
142
143
    /**
144
     * @inheritdoc
145
     */
146 57
    public function has($path)
147
    {
148 57
        return isset($this->storage[$path]);
149
    }
150
151
    /**
152
     * @inheritdoc
153
     */
154 3
    public function listContents($directory = '', $recursive = false)
155
    {
156 3
        $contents = $this->doListContents($directory, $recursive);
157
158 3
        return array_map([$this, 'getMetadata'], array_values($contents));
159
    }
160
161
    /**
162
     * @inheritdoc
163
     */
164 9
    public function read($path)
165
    {
166
        return [
167 9
            'path' => $path,
168 9
            'contents' => $this->storage[$path]['contents'],
169 3
        ];
170
    }
171
172
    /**
173
     * @inheritdoc
174
     */
175 3
    public function readStream($path)
176
    {
177 3
        $stream = fopen('php://memory', 'w+b');
178
179 3
        if ( ! is_resource($stream)) {
180
            throw new \RuntimeException('Unable to create memory stream.'); // @codeCoverageIgnore
181
        }
182
183 3
        fwrite($stream, $this->storage[$path]['contents']);
184 3
        rewind($stream);
185
186 3
        return compact('path', 'stream');
187
    }
188
189
    /**
190
     * @inheritdoc
191
     */
192 3
    public function rename($path, $newpath)
193
    {
194 3
        if ( ! $this->copy($path, $newpath)) {
195 3
            return false;
196
        }
197 3
        unset($this->storage[$path]);
198
199 3
        return true;
200
    }
201
202
    /**
203
     * @inheritdoc
204
     */
205 3
    public function setVisibility($path, $visibility)
206
    {
207 3
        if ( ! $this->hasFile($path)) {
208 3
            return false;
209
        }
210
211 3
        $this->storage[$path]['visibility'] = $visibility;
212
213 3
        return $this->getVisibility($path);
214
    }
215
216
    /**
217
     * @inheritdoc
218
     */
219 57
    public function update($path, $contents, Config $config)
220
    {
221 57
        if ( ! $this->hasFile($path)) {
222 3
            return false;
223
        }
224
225 57
        $this->storage[$path]['contents'] = $contents;
226 57
        $this->storage[$path]['timestamp'] = $config->get('timestamp', time());
227 57
        $this->storage[$path]['size'] = Util::contentSize($contents);
228 57
        $this->storage[$path]['visibility'] = $config->get('visibility', $this->storage[$path]['visibility']);
229
230 57
        return $this->getMetadata($path);
231
    }
232
233
    /**
234
     * @inheritdoc
235
     */
236 57
    public function write($path, $contents, Config $config)
237
    {
238
        // Make sure all the destination sub-directories exist.
239 57
        if ( ! $this->doCreateDir(Util::dirname($path), $config)) {
240 3
            return false;
241
        }
242
243 57
        $this->storage[$path]['type'] = 'file';
244 57
        $this->storage[$path]['visibility'] = AdapterInterface::VISIBILITY_PUBLIC;
245
246 57
        return $this->update($path, $contents, $config);
247
    }
248
249
    /**
250
     * Creates a directory.
251
     *
252
     * @param string $dirname
253
     * @param Config $config
254
     *
255
     * @return bool
256
     */
257 57
    protected function doCreateDir($dirname, Config $config)
258
    {
259 57
        if ($this->hasDirectory($dirname)) {
260 57
            return true;
261
        }
262
263 21
        if ($this->hasFile($dirname)) {
264 12
            return false;
265
        }
266
267
        // Make sure all the sub-directories exist.
268 18
        if ( ! $this->doCreateDir(Util::dirname($dirname), $config)) {
269 3
            return false;
270
        }
271
272 18
        $this->storage[$dirname]['type'] = 'dir';
273 18
        $this->storage[$dirname]['timestamp'] = $config->get('timestamp', time());
274
275 18
        return true;
276
    }
277
278
    /**
279
     * Filters the file system returning paths inside the directory.
280
     *
281
     *  @param string $directory
282
     *  @param bool   $recursive
283
     *
284
     * @return string[]
285
     */
286
    protected function doListContents($directory, $recursive)
287
    {
288 6
        $filter = function ($path) use ($directory, $recursive) {
289
            // Remove the root directory from any listing.
290 6
            if ($path === '') {
291 6
                return false;
292
            }
293
294 6
            if (Util::dirname($path) === $directory) {
295 6
                return true;
296
            }
297
298 6
            return $recursive && $this->pathIsInDirectory($path, $directory);
299 6
        };
300
301 6
        return array_filter(array_keys($this->storage), $filter);
302
    }
303
304
    /**
305
     * Checks whether a directory exists.
306
     *
307
     * @param string $path The directory.
308
     *
309
     * @return bool True if it exists, and is a directory, false if not.
310
     */
311 57
    protected function hasDirectory($path)
312
    {
313 57
        return $this->has($path) && $this->storage[$path]['type'] === 'dir';
314
    }
315
316
    /**
317
     * Checks whether a file exists.
318
     *
319
     * @param string $path The file.
320
     *
321
     * @return bool True if it exists, and is a file, false if not.
322
     */
323 57
    protected function hasFile($path)
324
    {
325 57
        return $this->has($path) && $this->storage[$path]['type'] === 'file';
326
    }
327
328
    /**
329
     * Determines if the path is inside the directory.
330
     *
331
     * @param string $path
332
     * @param string $directory
333
     *
334
     * @return bool
335
     */
336 6
    protected function pathIsInDirectory($path, $directory)
337
    {
338 6
        return $directory === '' || strpos($path, $directory . '/') === 0;
339
    }
340
}
341