Completed
Push — master ( 94294e...f9523f )
by Frank
9s
created

MountManager::filterPrefix()   B

Complexity

Conditions 6
Paths 6

Duplication

Lines 0
Ratio 0 %

Size

Total Lines 31
Code Lines 15

Code Coverage

Tests 13
CRAP Score 6

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 31
ccs 13
cts 13
cp 1
rs 8.439
cc 6
eloc 15
nc 6
nop 1
crap 6
1
<?php
2
3
namespace League\Flysystem;
4
5
use InvalidArgumentException;
6
use League\Flysystem\Plugin\PluggableTrait;
7
use League\Flysystem\Plugin\PluginNotFoundException;
8
use LogicException;
9
10
/**
11
 * Class MountManager.
12
 *
13
 * Proxies methods to Filesystem (@see __call):
14
 *
15
 * @method AdapterInterface getAdapter($prefix)
16
 * @method Config getConfig($prefix)
17
 * @method bool has($path)
18
 * @method bool write($path, $contents, array $config = [])
19
 * @method bool writeStream($path, $resource, array $config = [])
20
 * @method bool put($path, $contents, $config = [])
21
 * @method bool putStream($path, $contents, $config = [])
22
 * @method string readAndDelete($path)
23
 * @method bool update($path, $contents, $config = [])
24
 * @method bool updateStream($path, $resource, $config = [])
25
 * @method string|false read($path)
26
 * @method resource|false readStream($path)
27
 * @method bool rename($path, $newpath)
28
 * @method bool delete($path)
29
 * @method bool deleteDir($dirname)
30
 * @method bool createDir($dirname, $config = [])
31
 * @method array listFiles($directory = '', $recursive = false)
32
 * @method array listPaths($directory = '', $recursive = false)
33
 * @method array getWithMetadata($path, array $metadata)
34
 * @method string|false getMimetype($path)
35
 * @method string|false getTimestamp($path)
36
 * @method string|false getVisibility($path)
37
 * @method int|false getSize($path);
38
 * @method bool setVisibility($path, $visibility)
39
 * @method array|false getMetadata($path)
40
 * @method Handler get($path, Handler $handler = null)
41
 * @method Filesystem flushCache()
42
 * @method assertPresent($path)
43
 * @method assertAbsent($path)
44
 * @method Filesystem addPlugin(PluginInterface $plugin)
45
 */
46
class MountManager
47
{
48
    use PluggableTrait;
49
50
    /**
51
     * @var array
52
     */
53
    protected $filesystems = [];
54
55
    /**
56
     * Constructor.
57
     *
58
     * @param array $filesystems
59
     */
60 45
    public function __construct(array $filesystems = [])
61
    {
62 45
        $this->mountFilesystems($filesystems);
63 45
    }
64
65
    /**
66
     * Mount filesystems.
67
     *
68
     * @param array $filesystems [:prefix => Filesystem,]
69
     *
70
     * @return $this
71
     */
72 45
    public function mountFilesystems(array $filesystems)
73
    {
74 45
        foreach ($filesystems as $prefix => $filesystem) {
75 3
            $this->mountFilesystem($prefix, $filesystem);
76 45
        }
77
78 45
        return $this;
79
    }
80
81
    /**
82
     * Mount filesystems.
83
     *
84
     * @param string              $prefix
85
     * @param FilesystemInterface $filesystem
86
     *
87
     * @return $this
88
     */
89 33
    public function mountFilesystem($prefix, FilesystemInterface $filesystem)
90
    {
91 33
        if ( ! is_string($prefix)) {
92 3
            throw new InvalidArgumentException(__METHOD__ . ' expects argument #1 to be a string.');
93
        }
94
95 30
        $this->filesystems[$prefix] = $filesystem;
96
97 30
        return $this;
98
    }
99
100
    /**
101
     * Get the filesystem with the corresponding prefix.
102
     *
103
     * @param string $prefix
104
     *
105
     * @throws LogicException
106
     *
107
     * @return FilesystemInterface
108
     */
109 33
    public function getFilesystem($prefix)
110
    {
111 33
        if ( ! isset($this->filesystems[$prefix])) {
112 3
            throw new LogicException('No filesystem mounted with prefix ' . $prefix);
113
        }
114
115 30
        return $this->filesystems[$prefix];
116
    }
117
118
    /**
119
     * Retrieve the prefix from an arguments array.
120
     *
121
     * @param array $arguments
122
     *
123
     * @return array [:prefix, :arguments]
124
     */
125 36
    public function filterPrefix(array $arguments)
126
    {
127 36
        if (empty($arguments)) {
128 3
            throw new LogicException('At least one argument needed');
129
        }
130
131 33
        // The prefix depends on the first argument.
132
        $path = array_shift($arguments);
133 33
134 3
        if ( ! is_string($path)) {
135
            throw new InvalidArgumentException('First argument should be a string');
136
        }
137 30
138 3
        if ( ! preg_match('#^.+\:\/\/.*#', $path)) {
139
            throw new InvalidArgumentException('No prefix detected in path: ' . $path);
140
        }
141 27
142 27
        list($prefix, $path) = explode('://', $path, 2);
143
144 27
        // If there are more paths in the arguments, we'll fix them as well.
145
        foreach ($arguments as $key => $argument) {
146
            $parts = explode('://', $argument, 2);
147
            if (count($parts) == 2) {
148
                $arguments[$key] = $parts[1];
149
            }
150
        }
151
152
        array_unshift($arguments, $path);
153 3
154
        return [$prefix, $arguments];
155 3
    }
156 3
157 3
    /**
158 3
     * @param string $directory
159
     * @param bool   $recursive
160 3
     *
161 3
     * @return array
162 3
     */
163
    public function listContents($directory = '', $recursive = false)
164 3
    {
165
        list($prefix, $arguments) = $this->filterPrefix([$directory]);
166
        $filesystem = $this->getFilesystem($prefix);
167
        $directory = array_shift($arguments);
168
        $result = $filesystem->listContents($directory, $recursive);
169
170
        foreach ($result as &$file) {
171
            $file['filesystem'] = $prefix;
172
        }
173
174
        return $result;
175 15
    }
176
177 15
    /**
178
     * Call forwarder.
179 15
     *
180
     * @param string $method
181
     * @param array  $arguments
182
     *
183
     * @return mixed
184
     */
185
    public function __call($method, $arguments)
186
    {
187
        list($prefix, $arguments) = $this->filterPrefix($arguments);
188
189 6
        return $this->invokePluginOnFilesystem($method, $arguments, $prefix);
190
    }
191 6
192
    /**
193 6
     * @param $from
194 6
     * @param $to
195
     * @param array $config
196 6
     *
197 3
     * @return bool
198
     */
199
    public function copy($from, $to, array $config = [])
200 6
    {
201
        list($prefixFrom, $arguments) = $this->filterPrefix([$from]);
202 6
203 6
        $fsFrom = $this->getFilesystem($prefixFrom);
204
        $buffer = call_user_func_array([$fsFrom, 'readStream'], $arguments);
205 6
206 6
        if ($buffer === false) {
207 6
            return false;
208
        }
209 6
210
        list($prefixTo, $arguments) = $this->filterPrefix([$to]);
211
212
        $fsTo = $this->getFilesystem($prefixTo);
213
        $result =  call_user_func_array([$fsTo, 'writeStream'], array_merge($arguments, [$buffer, $config]));
214
215
        if (is_resource($buffer)) {
216
            fclose($buffer);
217
        }
218
219 3
        return $result;
220
    }
221 3
222 3
    /**
223 3
     * List with plugin adapter.
224
     *
225 3
     * @param array  $keys
226
     * @param string $directory
227
     * @param bool   $recursive
228
     */
229
    public function listWith(array $keys = [], $directory = '', $recursive = false)
230
    {
231
        list($prefix, $arguments) = $this->filterPrefix([$directory]);
232
        $directory = $arguments[0];
233
        $arguments = [$keys, $directory, $recursive];
234
235
        return $this->invokePluginOnFilesystem('listWith', $arguments, $prefix);
236
    }
237 3
238
    /**
239 3
     * Move a file.
240
     *
241 3
     * @param $from
242 3
     * @param $to
243
     * @param array $config
244
     *
245 3
     * @return bool
246
     */
247
    public function move($from, $to, array $config = [])
248
    {
249
        $copied = $this->copy($from, $to, $config);
250
251
        if ($copied) {
252
            return $this->delete($from);
253
        }
254
255
        return false;
256
    }
257 18
258
    /**
259 18
     * Invoke a plugin on a filesystem mounted on a given prefix.
260
     *
261
     * @param $method
262 18
     * @param $arguments
263 18
     * @param $prefix
264
     *
265
     * @return mixed
266
     */
267 18
    public function invokePluginOnFilesystem($method, $arguments, $prefix)
268
    {
269 18
        $filesystem = $this->getFilesystem($prefix);
270
271
        try {
272
            return $this->invokePlugin($method, $arguments, $filesystem);
273
        } catch (PluginNotFoundException $e) {
274
            // Let it pass, it's ok, don't panic.
275
        }
276
277
        $callback = [$filesystem, $method];
278
279
        return call_user_func_array($callback, $arguments);
280
    }
281
}
282