FallbackAdapter::rename()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.0416

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 12
ccs 5
cts 6
cp 0.8333
rs 9.4285
cc 3
eloc 6
nc 3
nop 2
crap 3.0416
1
<?php
2
3
namespace Litipk\Flysystem\Fallback;
4
5
use League\Flysystem\AdapterInterface;
6
use League\Flysystem\Config;
7
use League\Flysystem\FileNotFoundException;
8
9
class FallbackAdapter implements AdapterInterface
10
{
11
    /**
12
     * @var AdapterInterface
13
     */
14
    protected $mainAdapter;
15
16
    /**
17
     * @var AdapterInterface
18
     */
19
    protected $fallback;
20
21
    /**
22
     * @var bool
23
     */
24
    protected $forceCopyOnMain;
25
26
    /**
27
     * Constructor.
28
     *
29
     * @param AdapterInterface $mainAdapter
30
     * @param AdapterInterface $fallback
31
     * @param boolean          $forceCopyOnMain
32
     */
33 25
    public function __construct(AdapterInterface $mainAdapter, AdapterInterface $fallback, $forceCopyOnMain = false)
34
    {
35 25
        $this->mainAdapter = $mainAdapter;
36 25
        $this->fallback = $fallback;
37 25
        $this->forceCopyOnMain = $forceCopyOnMain;
38 25
    }
39
40
    /**
41
     * Returns the main adapter.
42
     *
43
     * @return AdapterInterface
44
     */
45 1
    public function getMainAdapter()
46
    {
47 1
        return $this->mainAdapter;
48
    }
49
50
    /**
51
     * Returns the fallback adapter.
52
     *
53
     * @return AdapterInterface
54
     */
55 1
    public function getFallbackAdapter()
56
    {
57 1
        return $this->fallback;
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63 1
    public function write($path, $contents, Config $config)
64
    {
65 1
        return $this->mainAdapter->write($path, $contents, $config);
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71 1
    public function writeStream($path, $resource, Config $config)
72
    {
73 1
        return $this->mainAdapter->writeStream($path, $resource, $config);
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79 2
    public function update($path, $contents, Config $config)
80
    {
81
        // This is done to allow "append" mode in the underlying main adapter
82 2
        if (!$this->mainAdapter->has($path) && $this->fallback->has($path)) {
83 1
            $this->portFromFallback($path, $path);
84 1
        }
85
86 2
        return $this->mainAdapter->update($path, $contents, $config);
87
    }
88
89
    /**
90
     * {@inheritdoc}
91
     */
92 2
    public function updateStream($path, $resource, Config $config)
93
    {
94 2
        if ($this->mainAdapter->has($path)) {
95 1
            return $this->mainAdapter->updateStream($path, $resource, $config);
96
        } else {
97
            // TODO: Review, is this necessary?
98 1
            return $this->mainAdapter->writeStream($path, $resource, $config);
99
        }
100
    }
101
102
    /**
103
     * {@inheritdoc}
104
     */
105 2
    public function rename($path, $newpath)
106
    {
107 2
        if ($this->mainAdapter->has($path)) {
108 1
            return $this->mainAdapter->rename($path, $newpath);
109
        }
110
111 1
        if (false !== $this->portFromFallback($path, $newpath)) {
112 1
            return $this->fallback->delete($path);
113
        }
114
115
        return false;
116
    }
117
118
    /**
119
     * {@inheritdoc}
120
     */
121 3
    public function copy($path, $newpath)
122
    {
123 3
        if ($this->mainAdapter->has($path)) {
124 1
            return $this->mainAdapter->copy($path, $newpath);
125 2
        } elseif ($this->fallback->has($path)) {
126 1
            return $this->portFromFallback($path, $newpath);
127
        }
128
129 1
        return false;
130
    }
131
132
    /**
133
     * {@inheritdoc}
134
     */
135 3
    public function delete($path)
136
    {
137 3
        $found = false;
138
139 3
        if ($this->fallback->has($path)) {
140 2
            $fallbackResult = $this->fallback->delete($path);
141 2
            $found = true;
142 2
        } else {
143 1
            $fallbackResult = true;
144
        }
145
146 3
        if ($this->mainAdapter->has($path)) {
147 2
            $mainResult = $this->mainAdapter->delete($path);
148 2
            $found = true;
149 2
        } else {
150 1
            $mainResult = true;
151
        }
152
153 3
        if (!$found) {
154
            throw new FileNotFoundException($path);
155
        }
156
157 3
        return ($fallbackResult && $mainResult);
158
    }
159
160
    /**
161
     * {@inheritdoc}
162
     */
163
    public function deleteDir($dirname)
164
    {
165
        $found = false;
166
167
        if ($this->fallback->has($dirname)) {
168
            $fallbackResult = $this->fallback->deleteDir($dirname);
169
            $found = true;
170
        } else {
171
            $fallbackResult = true;
172
        }
173
174
        if ($this->mainAdapter->has($dirname)) {
175
            $mainResult = $this->mainAdapter->deleteDir($dirname);
176
            $found = true;
177
        } else {
178
            $mainResult = true;
179
        }
180
181
        if (!$found) {
182
            throw new FileNotFoundException($dirname);
183
        }
184
185
        return ($fallbackResult && $mainResult);
186
    }
187
188
    /**
189
     * {@inheritdoc}
190
     */
191
    public function createDir($dirname, Config $config)
192
    {
193
        return $this->mainAdapter->createDir($dirname, $config);
194
    }
195
196
    /**
197
     * {@inheritdoc}
198
     */
199
    public function setVisibility($path, $visibility)
200
    {
201
        if ($this->mainAdapter->has($path)) {
202
            return $this->mainAdapter->setVisibility($path, $visibility);
203
        }
204
205
        return $this->fallback->setVisibility($path, $visibility);
206
    }
207
208
    /**
209
     * {@inheritdoc}
210
     */
211 3
    public function has($path)
212
    {
213 3
        return $this->mainAdapter->has($path) || $this->fallback->has($path);
214
    }
215
216
    /**
217
     * {@inheritdoc}
218
     */
219 2
    public function read($path)
220
    {
221 2
        $result = $this->mainAdapter->read($path);
222
223 2
        if (false !== $result) {
224 1
            return $result;
225
        }
226
227 1
        $result = $this->fallback->read($path);
228
229 1
        if (false !== $result && $this->forceCopyOnMain) {
230
            $this->mainAdapter->write($path, $result['contents'], new Config());
231
        }
232
233 1
        return $result;
234
    }
235
236
    /**
237
     * {@inheritdoc}
238
     */
239
    public function readStream($path)
240
    {
241
        $result = $this->mainAdapter->readStream($path);
242
243
        if (false !== $result) {
244
            return $result;
245
        }
246
247
        $result = $this->fallback->readStream($path);
248
249
        if (false !== $result && $this->forceCopyOnMain) {
250
            $this->writeStream($path, $result['stream'], new Config());
251
        }
252
253
        return $result;
254
    }
255
256
    /**
257
     * {@inheritdoc}
258
     */
259 1
    public function listContents($directory = '', $recursive = false)
260
    {
261 1
        $tmpResult = $this->mainAdapter->listContents($directory, $recursive);
262
263 1
        $inverseRef = [];
264 1
        foreach ($tmpResult as $index => $mainContent) {
265 1
            $inverseRef[$mainContent['path']] = $index;
266 1
        }
267
268 1
        $fallbackContents = $this->fallback->listContents($directory, $recursive);
269 1
        foreach ($fallbackContents as $fallbackContent) {
270 1
            if (!isset($inverseRef[$fallbackContent['path']])) {
271 1
                $tmpResult[] = $fallbackContent;
272 1
            }
273 1
        }
274
275 1
        return $tmpResult;
276
    }
277
278
    /**
279
     * {@inheritdoc}
280
     */
281
    public function getMetadata($path)
282
    {
283
        if ($this->mainAdapter->has($path)) {
284
            return $this->mainAdapter->getMetadata($path);
285
        }
286
287
        return $this->fallback->getMetadata($path);
288
    }
289
290
    /**
291
     * {@inheritdoc}
292
     */
293
    public function getSize($path)
294
    {
295
        if ($this->mainAdapter->has($path)) {
296
            return $this->mainAdapter->getSize($path);
297
        }
298
299
        return $this->fallback->getSize($path);
300
    }
301
302
    /**
303
     * {@inheritdoc}
304
     */
305
    public function getMimetype($path)
306
    {
307
        if ($this->mainAdapter->has($path)) {
308
            return $this->mainAdapter->getMimetype($path);
309
        }
310
311
        return $this->fallback->getMimetype($path);
312
    }
313
314
    /**
315
     * {@inheritdoc}
316
     */
317
    public function getTimestamp($path)
318
    {
319
        if ($this->mainAdapter->has($path)) {
320
            return $this->mainAdapter->getTimestamp($path);
321
        }
322
323
        return $this->fallback->getTimestamp($path);
324
    }
325
326
    /**
327
     * {@inheritdoc}
328
     */
329 2
    public function getVisibility($path)
330
    {
331 2
        if ($this->mainAdapter->has($path)) {
332 1
            return $this->mainAdapter->getVisibility($path);
333
        }
334
335 1
        return $this->fallback->getVisibility($path);
336
    }
337
338
    /**
339
     * Copies a resource accessible through the fallback adapter to the filesystem abstracted with the main adapter.
340
     *
341
     * @param $path
342
     * @return boolean
343
     */
344 3
    private function portFromFallback($path, $newpath)
345
    {
346 3
        $buffer = $this->fallback->readStream($path);
347
348 3
        if (false === $buffer) {
349
            return false;
350
        }
351
352 3
        $result = $this->mainAdapter->writeStream($newpath, $buffer['stream'], new Config());
353
354 3
        if (is_resource($buffer['stream'])) {
355
            fclose($buffer['stream']);
356
        }
357
358 3
        return (false !== $result);
359
    }
360
}
361