Completed
Pull Request — master (#2)
by Chris
20:40
created

MemoryAdapter::write()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

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