Completed
Push — master ( 7e8f5f...1cabec )
by Chris
02:28
created

MemoryAdapter::doCreateDir()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 4

Importance

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