Completed
Push — master ( 4eac1a...ebb03c )
by Frank
07:59 queued 03:51
created

AbstractCache::pathIsInDirectory()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2.5

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 4
cp 0.5
rs 10
c 0
b 0
f 0
cc 2
eloc 2
nc 2
nop 2
crap 2.5
1
<?php
2
3
namespace League\Flysystem\Cached\Storage;
4
5
use League\Flysystem\Cached\CacheInterface;
6
use League\Flysystem\Util;
7
8
abstract class AbstractCache implements CacheInterface
9
{
10
    /**
11
     * @var bool
12
     */
13
    protected $autosave = true;
14
15
    /**
16
     * @var array
17
     */
18
    protected $cache = [];
19
20
    /**
21
     * @var array
22
     */
23
    protected $complete = [];
24
25
    /**
26
     * Destructor.
27
     */
28 147
    public function __destruct()
29
    {
30 147
        if (! $this->autosave) {
31 6
            $this->save();
32 6
        }
33 147
    }
34
35
    /**
36
     * Get the autosave setting.
37
     *
38
     * @return bool autosave
39
     */
40 3
    public function getAutosave()
41
    {
42 3
        return $this->autosave;
43
    }
44
45
    /**
46
     * Get the autosave setting.
47
     *
48
     * @param bool $autosave
49
     */
50 3
    public function setAutosave($autosave)
51
    {
52 3
        $this->autosave = $autosave;
53 3
    }
54
55
    /**
56
     * Store the contents listing.
57
     *
58
     * @param string $directory
59
     * @param array  $contents
60
     * @param bool   $recursive
61
     *
62
     * @return array contents listing
63
     */
64 15
    public function storeContents($directory, array $contents, $recursive = false)
65
    {
66 15
        $directories = [$directory];
67
68 15
        foreach ($contents as $object) {
69 15
            $this->updateObject($object['path'], $object);
70 15
            $object = $this->cache[$object['path']];
71
72 15
            if ($recursive && $this->pathIsInDirectory($directory, $object['path'])) {
73 9
                $directories[] = $object['dirname'];
74 9
            }
75 15
        }
76
77 15
        foreach (array_unique($directories) as $directory) {
78 15
            $this->setComplete($directory, $recursive);
79 15
        }
80
81 15
        $this->autosave();
82 15
    }
83
84
    /**
85
     * Update the metadata for an object.
86
     *
87
     * @param string $path     object path
88
     * @param array  $object   object metadata
89
     * @param bool   $autosave whether to trigger the autosave routine
90
     */
91 48
    public function updateObject($path, array $object, $autosave = false)
92
    {
93 48
        if (! $this->has($path)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->has($path) of type boolean|null is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
94 48
            $this->cache[$path] = Util::pathinfo($path);
95 48
        }
96
97 48
        $this->cache[$path] = array_merge($this->cache[$path], $object);
98
99 48
        if ($autosave) {
100 21
            $this->autosave();
101 21
        }
102
103 48
        $this->ensureParentDirectories($path);
104 48
    }
105
106
    /**
107
     * Store object hit miss.
108
     *
109
     * @param string $path
110
     */
111 6
    public function storeMiss($path)
112
    {
113 6
        $this->cache[$path] = false;
114 6
        $this->autosave();
115 6
    }
116
117
    /**
118
     * Get the contents listing.
119
     *
120
     * @param string $dirname
121
     * @param bool   $recursive
122
     *
123
     * @return array contents listing
124
     */
125 9
    public function listContents($dirname = '', $recursive = false)
126
    {
127 9
        $result = [];
128
129 9
        foreach ($this->cache as $object) {
130 9
            if ($object['dirname'] === $dirname) {
131 9
                $result[] = $object;
132 9
            } elseif ($recursive && $this->pathIsInDirectory($dirname, $object['path'])) {
133 3
                $result[] = $object;
134 3
            }
135 9
        }
136
137 9
        return $result;
138
    }
139
140
    /**
141
     * {@inheritdoc}
142
     */
143 60
    public function has($path)
144
    {
145 60
        if ($path !== false && array_key_exists($path, $this->cache)) {
146 18
            return $this->cache[$path] !== false;
147
        }
148
149 54
        if ($this->isComplete(Util::dirname($path), false)) {
150 3
            return false;
151
        }
152 51
    }
153
154
    /**
155
     * {@inheritdoc}
156
     */
157 12
    public function read($path)
158
    {
159 12
        if (isset($this->cache[$path]['contents']) && $this->cache[$path]['contents'] !== false) {
160 6
            return $this->cache[$path];
161
        }
162
163 9
        return false;
164
    }
165
166
    /**
167
     * {@inheritdoc}
168
     */
169 3
    public function readStream($path)
170
    {
171 3
        return false;
172
    }
173
174
    /**
175
     * {@inheritdoc}
176
     */
177 3
    public function rename($path, $newpath)
178
    {
179 3
        if ($this->has($path)) {
180 3
            $object = $this->cache[$path];
181 3
            unset($this->cache[$path]);
182 3
            $object['path'] = $newpath;
183 3
            $object = array_merge($object, Util::pathinfo($newpath));
184 3
            $this->cache[$newpath] = $object;
185 3
            $this->autosave();
186 3
        }
187 3
    }
188
189
    /**
190
     * {@inheritdoc}
191
     */
192 6
    public function copy($path, $newpath)
193
    {
194 6
        if ($this->has($path)) {
195 3
            $object = $this->cache[$path];
196 3
            $object = array_merge($object, Util::pathinfo($newpath));
197 3
            $this->updateObject($newpath, $object, true);
198 3
        }
199 6
    }
200
201
    /**
202
     * {@inheritdoc}
203
     */
204 3
    public function delete($path)
205
    {
206 3
        $this->storeMiss($path);
207 3
    }
208
209
    /**
210
     * {@inheritdoc}
211
     */
212 6
    public function deleteDir($dirname)
213
    {
214 6
        foreach ($this->cache as $path => $object) {
215 6
            if ($this->pathIsInDirectory($dirname, $path) || $path === $dirname) {
216 6
                unset($this->cache[$path]);
217 6
            }
218 6
        }
219
220 6
        unset($this->complete[$dirname]);
221
222 6
        $this->autosave();
223 6
    }
224
225
    /**
226
     * {@inheritdoc}
227
     */
228 6
    public function getMimetype($path)
229
    {
230 6
        if (isset($this->cache[$path]['mimetype'])) {
231 3
            return $this->cache[$path];
232
        }
233
234 6
        if (! $result = $this->read($path)) {
235 3
            return false;
236
        }
237
238 3
        $mimetype = Util::guessMimeType($path, $result['contents']);
239 3
        $this->cache[$path]['mimetype'] = $mimetype;
240
241 3
        return $this->cache[$path];
242
    }
243
244
    /**
245
     * {@inheritdoc}
246
     */
247 3
    public function getSize($path)
248
    {
249 3
        if (isset($this->cache[$path]['size'])) {
250 3
            return $this->cache[$path];
251
        }
252
253 3
        return false;
254
    }
255
256
    /**
257
     * {@inheritdoc}
258
     */
259 3
    public function getTimestamp($path)
260
    {
261 3
        if (isset($this->cache[$path]['timestamp'])) {
262 3
            return $this->cache[$path];
263
        }
264
265 3
        return false;
266
    }
267
268
    /**
269
     * {@inheritdoc}
270
     */
271 3
    public function getVisibility($path)
272
    {
273 3
        if (isset($this->cache[$path]['visibility'])) {
274 3
            return $this->cache[$path];
275
        }
276
277 3
        return false;
278
    }
279
280
    /**
281
     * {@inheritdoc}
282
     */
283 18
    public function getMetadata($path)
284
    {
285 18
        if (isset($this->cache[$path]['type'])) {
286 15
            return $this->cache[$path];
287
        }
288
289 3
        return false;
290
    }
291
292
    /**
293
     * {@inheritdoc}
294
     */
295 99
    public function isComplete($dirname, $recursive)
296
    {
297 99
        if (! array_key_exists($dirname, $this->complete)) {
298 75
            return false;
299
        }
300
301 33
        if ($recursive && $this->complete[$dirname] !== 'recursive') {
302 3
            return false;
303
        }
304
305 33
        return true;
306
    }
307
308
    /**
309
     * {@inheritdoc}
310
     */
311 24
    public function setComplete($dirname, $recursive)
312
    {
313 24
        $this->complete[$dirname] = $recursive ? 'recursive' : true;
314 24
    }
315
316
    /**
317
     * Filter the contents from a listing.
318
     *
319
     * @param array $contents object listing
320
     *
321
     * @return array filtered contents
322
     */
323 39
    public function cleanContents(array $contents)
324
    {
325 39
        $cachedProperties = array_flip([
326 39
            'path', 'dirname', 'basename', 'extension', 'filename',
327 39
            'size', 'mimetype', 'visibility', 'timestamp', 'type',
328 39
        ]);
329
330 39
        foreach ($contents as $path => $object) {
331 12
            if (is_array($object)) {
332 12
                $contents[$path] = array_intersect_key($object, $cachedProperties);
333 12
            }
334 39
        }
335
336 39
        return $contents;
337
    }
338
339
    /**
340
     * {@inheritdoc}
341
     */
342 3
    public function flush()
343
    {
344 3
        $this->cache = [];
345 3
        $this->complete = [];
346 3
        $this->autosave();
347 3
    }
348
349
    /**
350
     * {@inheritdoc}
351
     */
352 51
    public function autosave()
353
    {
354 51
        if ($this->autosave) {
355 51
            $this->save();
356 51
        }
357 51
    }
358
359
    /**
360
     * Retrieve serialized cache data.
361
     *
362
     * @return string serialized data
363
     */
364 24
    public function getForStorage()
365
    {
366 24
        $cleaned = $this->cleanContents($this->cache);
367
368 24
        return json_encode([$cleaned, $this->complete]);
369
    }
370
371
    /**
372
     * Load from serialized cache data.
373
     *
374
     * @param string $json
375
     */
376 18
    public function setFromStorage($json)
377
    {
378 18
        list($cache, $complete) = json_decode($json, true);
379
380 18
        if (json_last_error() === JSON_ERROR_NONE && is_array($cache) && is_array($complete)) {
381 18
            $this->cache = $cache;
382 18
            $this->complete = $complete;
383 18
        }
384 18
    }
385
386
    /**
387
     * Ensure parent directories of an object.
388
     *
389
     * @param string $path object path
390
     */
391 48
    public function ensureParentDirectories($path)
392
    {
393 48
        $object = $this->cache[$path];
394
395 48
        while ($object['dirname'] !== '' && ! isset($this->cache[$object['dirname']])) {
396 12
            $object = Util::pathinfo($object['dirname']);
397 12
            $object['type'] = 'dir';
398 12
            $this->cache[$object['path']] = $object;
399 12
        }
400 48
    }
401
402
    /**
403
     * Determines if the path is inside the directory.
404
     *
405
     * @param string $directory
406
     * @param string $path
407
     *
408
     * @return bool
409
     */
410 18
    protected function pathIsInDirectory($directory, $path)
411
    {
412 18
        return $directory === '' || strpos($path, $directory . '/') === 0;
413
    }
414
}
415