Completed
Pull Request — master (#6)
by Mathieu
01:56
created

FilesystemServiceProvider::createLocalAdapter()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
rs 8.6845
c 0
b 0
f 0
cc 4
eloc 14
nc 3
nop 1
1
<?php
2
3
namespace Charcoal\App\ServiceProvider;
4
5
use Exception;
6
use LogicException;
7
use InvalidArgumentException;
8
use UnexpectedValueException;
9
10
// Dependencies from `pimple/pimple`
11
use Pimple\ServiceProviderInterface;
12
use Pimple\Container;
13
14
// Dependencies from AWS S3 SDK
15
use Aws\S3\S3Client;
16
17
// Dependencies from Dropbox
18
use Dropbox\Client as DropboxClient;
19
20
// Dependencies from `league/flysystem`
21
use League\Flysystem\MountManager;
22
use League\Flysystem\Filesystem;
23
use League\Flysystem\Adapter\Local as LocalAdapter;
24
use League\Flysystem\Adapter\Ftp as FtpAdapter;
25
use League\Flysystem\Adapter\NullAdapter;
26
27
// Dependency from `league/flysystem-aws-s3-v3`
28
use League\Flysystem\AwsS3v3\AwsS3Adapter;
29
30
// Dependency from `league/flysystem-dropbox`
31
use League\Flysystem\Dropbox\DropboxAdapter;
32
33
// Dependency from `league/flysystem-sftp`
34
use League\Flysystem\Sftp\SftpAdapter;
35
36
// Dependency from `league/flysystem-memory`
37
use League\Flysystem\Memory\MemoryAdapter;
38
39
// Local namespace depdency
40
use Charcoal\App\Config\FilesystemConfig;
41
42
/**
43
 *
44
 */
45
class FilesystemServiceProvider implements ServiceProviderInterface
46
{
47
    /**
48
     * @param Container $container Pimple DI Container.
49
     * @return void
50
     */
51
    public function register(Container $container)
52
    {
53
        /**
54
         * @param  Container $container Pimple DI Container.
55
         * @return FlysystemConfig
56
         */
57 View Code Duplication
        $container['filesystem/config'] = function (Container $container) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
58
            $appConfig = isset($container['config']) ? $container['config'] : [];
59
            $fsConfig  = isset($appConfig['filesystem']) ? $appConfig['filesystem'] : null;
60
            return new FilesystemConfig($fsConfig);
61
        };
62
63
        /**
64
         * @param Container $container Pimple DI Container.
65
         * @return MountManager
66
         */
67
        $container['filesystem/manager'] = function () {
68
            return new MountManager();
69
        };
70
71
        $container['filesystems'] = function (Container $container) {
72
            $filesystemConfig = $container['filesystem/config'];
73
            $filesystems = new Container();
74
75
            foreach ($filesystemConfig['connections'] as $ident => $connection) {
76
                $fs = $this->createConnection($connection);
77
                $filesystems[$ident] = $fs;
78
                $container['filesystem/manager']->mountFilesystem($ident, $fs);
79
            }
80
81
            return $filesystems;
82
        };
83
    }
84
85
    /**
86
     * @param array $config The driver (adapter) configuration.
87
     * @throws Exception If the filesystem type is not defined in config.
88
     * @throws UnexpectedValueException If the filesystem type is invalid / unsupported.
89
     * @return Filesystem
90
     */
91
    private function createConnection(array $config)
92
    {
93
        if (!isset($config['type'])) {
94
            throw new Exception(
95
                'No filesystem type defined'
96
            );
97
        }
98
99
        $type = $config['type'];
100
101
        if ($type == 'local') {
102
            $adapter = $this->createLocalAdapter($config);
103
        } elseif ($type == 's3') {
104
            $adapter = $this->createS3Adapter($config);
105
        } elseif ($type == 'dropbox') {
106
            $adapter = $this->createDropboxAdapter($config);
107
        } elseif ($type == 'ftp') {
108
            $adapter = $this->createFtpAdapter($config);
109
        } elseif ($type == 'sftp') {
110
            $adapter = $this->createSftpAdapter($config);
111
        } elseif ($type == 'memory') {
112
            $adapter = $this->createMemoryAdapter();
113
        } elseif ($type == 'noop') {
114
            $adapter = $this->createNullAdapter();
115
        } else {
116
            throw new UnexpectedValueException(
117
                sprintf('Invalid filesystem type "%s"', $type)
118
            );
119
        }
120
121
        return new Filesystem($adapter);
122
    }
123
124
    /**
125
     * @param array $config The driver (adapter) configuration.
126
     * @throws InvalidArgumentException If the path is not defined.
127
     * @throws LogicException If the path is not accessible.
128
     * @return LocalAdapter
129
     */
130
    private function createLocalAdapter(array $config)
131
    {
132
        if (!isset($config['path']) || !$config['path']) {
133
            throw new InvalidArgumentException(
134
                'No "path" configured for local filesystem.'
135
            );
136
        }
137
138
        $path = realpath($config['path']);
139
        if ($path === false) {
140
            throw new LogicException(
141
                'Filesystem "path" does not exist.'
142
            );
143
        }
144
145
        $defaults = [
146
            'lock'        => null,
147
            'links'       => null,
148
            'permissions' => []
149
        ];
150
        $config = array_merge($defaults, $config);
151
152
        return new LocalAdapter($config['path'], $config['lock'], $config['links'], $config['permissions']);
153
    }
154
155
    /**
156
     * @param array $config The driver (adapter) configuration.
157
     * @throws InvalidArgumentException If the key, secret or bucket is not defined in config.
158
     * @return AwsS3Adapter
159
     */
160
    private function createS3Adapter(array $config)
161
    {
162
        if (!isset($config['key']) || !$config['key']) {
163
            throw new InvalidArgumentException(
164
                'No "key" configured for S3 filesystem.'
165
            );
166
        }
167
        if (!isset($config['secret']) || !$config['secret']) {
168
            throw new InvalidArgumentException(
169
                'No "secret" configured for S3 filesystem.'
170
            );
171
        }
172
173
        if (!isset($config['bucket']) || !$config['bucket']) {
174
            throw new InvalidArgumentException(
175
                'No "bucket" configured for S3 filesystem.'
176
            );
177
        }
178
179
        $defaults = [
180
            'region'  => '',
181
            'version' => 'latest',
182
            'prefix'  => null
183
        ];
184
        $config = array_merge($defaults, $config);
185
186
        $client = S3Client::factory([
0 ignored issues
show
Deprecated Code introduced by
The method Aws\AwsClient::factory() has been deprecated.

This method has been deprecated.

Loading history...
187
            'credentials' => [
188
                'key'    => $config['key'],
189
                'secret' => $config['secret'],
190
            ],
191
            'region'      => $config['region'],
192
            'version'     => $config['version'],
193
        ]);
194
195
        if (isset($config['public']) && !$config['public']) {
196
            $permissions = null;
197
        } else {
198
            $permissions = [
199
                'ACL' => 'public-read'
200
            ];
201
        }
202
203
        return new AwsS3Adapter($client, $config['bucket'], $config['prefix'], $permissions);
0 ignored issues
show
Bug introduced by
It seems like $permissions defined by null on line 196 can also be of type null; however, League\Flysystem\AwsS3v3...3Adapter::__construct() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
204
    }
205
206
    /**
207
     * @param array $config The driver (adapter) configuration.
208
     * @throws InvalidArgumentException If the token or secret is not defined in config.
209
     * @return DropboxAdapter
210
     */
211
    private function createDropboxAdapter(array $config)
212
    {
213
        if (!isset($config['token']) || !$config['token']) {
214
            throw new InvalidArgumentException(
215
                'No access "token" configured for dropbox filesystem adapter.'
216
            );
217
        }
218
219
        if (!isset($config['secret']) || !$config['secret']) {
220
            throw new InvalidArgumentException(
221
                'No app "secret" configured for dropbox filesystem adapter.'
222
            );
223
        }
224
225
        $defaults = [
226
            'prefix' => ''
227
        ];
228
        $config = array_merge($defaults, $config);
229
230
        $client = new DropboxClient($config['token'], $config['secret']);
231
        return new DropboxAdapter($client, $config['prefix']);
232
    }
233
234
    /**
235
     * @param array $config The driver (adapter) configuration.
236
     * @throws InvalidArgumentException If the host, username or password is not defined in config.
237
     * @return FtpAdapter
238
     */
239 View Code Duplication
    private function createFtpAdapter(array $config)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
240
    {
241
        if (!$config['host']) {
242
            throw new InvalidArgumentException(
243
                'No host configured for FTP filesystem adapter.'
244
            );
245
        }
246
        if (!$config['username']) {
247
            throw new InvalidArgumentException(
248
                'No username configured for FTP filesystem adapter.'
249
            );
250
        }
251
        if (!$config['password']) {
252
            throw new InvalidArgumentException(
253
                'No password configured for FTP filesystem adapter.'
254
            );
255
        }
256
257
        $defaults = [
258
            'port'    => null,
259
            'root'    => null,
260
            'passive' => null,
261
            'ssl'     => null,
262
            'timeout' => null
263
        ];
264
        $config = array_merge($defaults, $config);
265
266
        return new FtpAdapter($config);
267
    }
268
269
    /**
270
     * @param array $config The driver (adapter) configuration.
271
     * @throws InvalidArgumentException If the host, username or password is not defined in config.
272
     * @return SftpAdapter
273
     */
274 View Code Duplication
    private function createSftpAdapter(array $config)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
275
    {
276
        if (!$config['host']) {
277
            throw new InvalidArgumentException(
278
                'No host configured for SFTP filesystem adapter.'
279
            );
280
        }
281
        if (!$config['username']) {
282
            throw new InvalidArgumentException(
283
                'No username configured for SFTP filesystem adapter.'
284
            );
285
        }
286
        if (!$config['password']) {
287
            throw new InvalidArgumentException(
288
                'No password configured for SFTP filesystem adapter.'
289
            );
290
        }
291
292
        $defaults = [
293
            'port'       => null,
294
            'privateKey' => null,
295
            'root'       => null,
296
            'timeout'    => null
297
        ];
298
        $config = array_merge($defaults, $config);
299
300
        return new SftpAdapter($config);
301
    }
302
303
    /**
304
     * @return MemoryAdapter
305
     */
306
    private function createMemoryAdapter()
307
    {
308
        return new MemoryAdapter();
309
    }
310
311
    /**
312
     * @return NullAdapter
313
     */
314
    private function createNullAdapter()
315
    {
316
        return new NullAdapter();
317
    }
318
}
319