Completed
Pull Request — master (#3)
by
unknown
03:04
created

FallbackAdapter::portFromFallback()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3.1406

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 6
cts 8
cp 0.75
rs 9.7333
c 0
b 0
f 0
cc 3
nc 3
nop 2
crap 3.1406
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
        }
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
        } 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
        } 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
        if ($this->mainAdapter->has($path)) {
222 1
            return $this->mainAdapter->read($path);
223
        }
224
225 1
        $result = $this->fallback->read($path);
226
227 1
        if (false !== $result && $this->forceCopyOnMain) {
228
            $this->mainAdapter->write($path, $result['contents'], new Config());
229
        }
230
231 1
        return $result;
232
    }
233
234
    /**
235
     * {@inheritdoc}
236
     */
237
    public function readStream($path)
238
    {
239
        if ($this->mainAdapter->has($path)) {
240
            return $this->mainAdapter->readStream($path);
241
        }
242
243
        $result = $this->fallback->readStream($path);
244
245
        if (false !== $result && $this->forceCopyOnMain) {
246
            $this->writeStream($path, $result['stream'], new Config());
247
        }
248
249
        return $result;
250
    }
251
252
    /**
253
     * {@inheritdoc}
254
     */
255 1
    public function listContents($directory = '', $recursive = false)
256
    {
257 1
        $tmpResult = $this->mainAdapter->listContents($directory, $recursive);
258
259 1
        $inverseRef = [];
260 1
        foreach ($tmpResult as $index => $mainContent) {
261 1
            $inverseRef[$mainContent['path']] = $index;
262
        }
263
264 1
        $fallbackContents = $this->fallback->listContents($directory, $recursive);
265 1
        foreach ($fallbackContents as $fallbackContent) {
266 1
            if (!isset($inverseRef[$fallbackContent['path']])) {
267 1
                $tmpResult[] = $fallbackContent;
268
            }
269
        }
270
271 1
        return $tmpResult;
272
    }
273
274
    /**
275
     * {@inheritdoc}
276
     */
277
    public function getMetadata($path)
278
    {
279
        if ($this->mainAdapter->has($path)) {
280
            return $this->mainAdapter->getMetadata($path);
281
        }
282
283
        return $this->fallback->getMetadata($path);
284
    }
285
286
    /**
287
     * {@inheritdoc}
288
     */
289
    public function getSize($path)
290
    {
291
        if ($this->mainAdapter->has($path)) {
292
            return $this->mainAdapter->getSize($path);
293
        }
294
295
        return $this->fallback->getSize($path);
296
    }
297
298
    /**
299
     * {@inheritdoc}
300
     */
301
    public function getMimetype($path)
302
    {
303
        if ($this->mainAdapter->has($path)) {
304
            return $this->mainAdapter->getMimetype($path);
305
        }
306
307
        return $this->fallback->getMimetype($path);
308
    }
309
310
    /**
311
     * {@inheritdoc}
312
     */
313
    public function getTimestamp($path)
314
    {
315
        if ($this->mainAdapter->has($path)) {
316
            return $this->mainAdapter->getTimestamp($path);
317
        }
318
319
        return $this->fallback->getTimestamp($path);
320
    }
321
322
    /**
323
     * {@inheritdoc}
324
     */
325 2
    public function getVisibility($path)
326
    {
327 2
        if ($this->mainAdapter->has($path)) {
328 1
            return $this->mainAdapter->getVisibility($path);
329
        }
330
331 1
        return $this->fallback->getVisibility($path);
332
    }
333
334
    /**
335
     * Copies a resource accessible through the fallback adapter to the filesystem abstracted with the main adapter.
336
     *
337
     * @param $path
338
     * @return boolean
339
     */
340 3
    private function portFromFallback($path, $newpath)
341
    {
342 3
        $buffer = $this->fallback->readStream($path);
343
344 3
        if (false === $buffer) {
345
            return false;
346
        }
347
348 3
        $result = $this->mainAdapter->writeStream($newpath, $buffer['stream'], new Config());
349
350 3
        if (is_resource($buffer['stream'])) {
351
            fclose($buffer['stream']);
352
        }
353
354 3
        return (false !== $result);
355
    }
356
}
357