Test Setup Failed
Push — master ( 7fd538...e404d9 )
by Carlos
05:25 queued 10s
created

QiniuAdapter   C

Complexity

Total Complexity 55

Size/Duplication

Total Lines 578
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 88.55%

Importance

Changes 0
Metric Value
wmc 55
lcom 1
cbo 7
dl 0
loc 578
ccs 116
cts 131
cp 0.8855
rs 6
c 0
b 0
f 0

35 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A write() 0 23 3
A writeStream() 0 16 3
A update() 0 6 1
A updateStream() 0 6 1
A rename() 0 6 1
A copy() 0 6 1
A delete() 0 6 1
A deleteDir() 0 4 1
A createDir() 0 4 1
A has() 0 6 2
A getUrl() 0 7 2
A read() 0 6 1
A readStream() 0 10 2
A listContents() 0 12 3
A getMetadata() 0 7 1
A getSize() 0 4 1
A fetch() 0 10 2
A privateDownloadUrl() 0 4 1
A refresh() 0 11 2
A getMimeType() 0 10 2
A getTimestamp() 0 4 1
A setBucketManager() 0 6 1
A setUploadManager() 0 6 1
A setAuthManager() 0 6 1
A setCdnManager() 0 6 1
A getBucketManager() 0 4 2
A getAuthManager() 0 4 2
A getUploadManager() 0 4 2
A getCdnManager() 0 4 2
A getBucket() 0 4 1
A getUploadToken() 0 4 1
A normalizeFileInfo() 0 9 1
A normalizeHost() 0 8 3
A parse_url() 0 25 3

How to fix   Complexity   

Complex Class

Complex classes like QiniuAdapter often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use QiniuAdapter, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/*
4
 * This file is part of the overtrue/flysystem-qiniu.
5
 * (c) overtrue <[email protected]>
6
 * This source file is subject to the MIT license that is bundled
7
 * with this source code in the file LICENSE.
8
 */
9
10
namespace Overtrue\Flysystem\Qiniu;
11
12
use League\Flysystem\Adapter\AbstractAdapter;
13
use League\Flysystem\Adapter\Polyfill\NotSupportingVisibilityTrait;
14
use League\Flysystem\Config;
15
use Qiniu\Auth;
16
use Qiniu\Cdn\CdnManager;
17
use Qiniu\Storage\BucketManager;
18
use Qiniu\Storage\UploadManager;
19
20
/**
21
 * Class QiniuAdapter.
22
 *
23
 * @author overtrue <[email protected]>
24
 */
25
class QiniuAdapter extends AbstractAdapter
26
{
27
    use NotSupportingVisibilityTrait;
28
29
    /**
30
     * @var string
31
     */
32
    protected $accessKey;
33
34
    /**
35
     * @var string
36
     */
37
    protected $secretKey;
38
39
    /**
40
     * @var string
41
     */
42
    protected $bucket;
43
44
    /**
45
     * @var string
46
     */
47
    protected $domain;
48
49
    /**
50
     * @var \Qiniu\Auth
51
     */
52
    protected $authManager;
53
54
    /**
55
     * @var \Qiniu\Storage\UploadManager
56
     */
57
    protected $uploadManager;
58
59
    /**
60
     * @var \Qiniu\Storage\BucketManager
61
     */
62
    protected $bucketManager;
63
64
    /**
65
     * @var \Qiniu\Cdn\CdnManager
66
     */
67
    protected $cdnManager;
68
69
    /**
70
     * QiniuAdapter constructor.
71
     *
72
     * @param string $accessKey
73
     * @param string $secretKey
74
     * @param string $bucket
75
     * @param string $domain
76
     */
77 1
    public function __construct($accessKey, $secretKey, $bucket, $domain)
78
    {
79 1
        $this->accessKey = $accessKey;
80 1
        $this->secretKey = $secretKey;
81 1
        $this->bucket = $bucket;
82 1
        $this->domain = $domain;
83 1
    }
84
85
    /**
86
     * Write a new file.
87
     *
88
     * @param string $path
89
     * @param string $contents
90
     * @param Config $config   Config object
91
     *
92
     * @return array|false false on failure file meta data on success
93
     */
94 2
    public function write($path, $contents, Config $config)
95
    {
96 2
        $mime = 'application/octet-stream';
97
98 2
        if ($config->has('mime')) {
99 1
            $mime = $config->get('mime');
100 1
        }
101
102 2
        list($response, $error) = $this->getUploadManager()->put(
103 2
            $this->getAuthManager()->uploadToken($this->bucket),
104 2
            $path,
105 2
            $contents,
106 2
            null,
107 2
            $mime,
108
            $path
109 2
        );
110
111
        if ($error) {
112
            return false;
113
        }
114
115
        return $response;
116
    }
117
118
    /**
119
     * Write a new file using a stream.
120
     *
121
     * @param string   $path
122
     * @param resource $resource
123
     * @param Config   $config   Config object
124
     *
125
     * @return array|false false on failure file meta data on success
126
     */
127 1
    public function writeStream($path, $resource, Config $config)
128
    {
129 1
        $contents = '';
130
131 1
        while (!feof($resource)) {
132 1
            $contents .= fread($resource, 1024);
133 1
        }
134
135 1
        $response = $this->write($path, $contents, $config);
136
137 1
        if (false === $response) {
138 1
            return $response;
139
        }
140
141 1
        return compact('path');
142
    }
143
144
    /**
145
     * Update a file.
146
     *
147
     * @param string $path
148
     * @param string $contents
149
     * @param Config $config   Config object
150
     *
151
     * @return array|false false on failure file meta data on success
152
     */
153 1
    public function update($path, $contents, Config $config)
154
    {
155 1
        $this->delete($path);
156
157 1
        return $this->write($path, $contents, $config);
158
    }
159
160
    /**
161
     * Update a file using a stream.
162
     *
163
     * @param string   $path
164
     * @param resource $resource
165
     * @param Config   $config   Config object
166
     *
167
     * @return array|false false on failure file meta data on success
168
     */
169 1
    public function updateStream($path, $resource, Config $config)
170
    {
171 1
        $this->delete($path);
172
173 1
        return $this->writeStream($path, $resource, $config);
174
    }
175
176
    /**
177
     * Rename a file.
178
     *
179
     * @param string $path
180
     * @param string $newPath
181
     *
182
     * @return bool
183
     */
184 1
    public function rename($path, $newPath)
185
    {
186 1
        $response = $this->getBucketManager()->rename($this->bucket, $path, $newPath);
187
188 1
        return is_null($response);
189
    }
190
191
    /**
192
     * Copy a file.
193
     *
194
     * @param string $path
195
     * @param string $newPath
196
     *
197
     * @return bool
198
     */
199 1
    public function copy($path, $newPath)
200
    {
201 1
        $response = $this->getBucketManager()->copy($this->bucket, $path, $this->bucket, $newPath);
202
203 1
        return is_null($response);
204
    }
205
206
    /**
207
     * Delete a file.
208
     *
209
     * @param string $path
210
     *
211
     * @return bool
212
     */
213 1
    public function delete($path)
214
    {
215 1
        $response = $this->getBucketManager()->delete($this->bucket, $path);
216
217 1
        return is_null($response);
218
    }
219
220
    /**
221
     * Delete a directory.
222
     *
223
     * @param string $directory
224
     *
225
     * @return bool
226
     */
227 1
    public function deleteDir($directory)
228
    {
229 1
        return true;
230
    }
231
232
    /**
233
     * Create a directory.
234
     *
235
     * @param string $directory directory name
236
     * @param Config $config
237
     *
238
     * @return array|false
239
     */
240 1
    public function createDir($directory, Config $config)
241
    {
242 1
        return ['path' => $directory, 'type' => 'dir'];
243
    }
244
245
    /**
246
     * Check whether a file exists.
247
     *
248
     * @param string $path
249
     *
250
     * @return array|bool|null
251
     */
252 1
    public function has($path)
253
    {
254 1
        list($response, $error) = $this->getBucketManager()->stat($this->bucket, $path);
255
256 1
        return !$error || is_array($response);
257
    }
258
259
    /**
260
     * Get resource url.
261
     *
262
     * @param string $path
263
     *
264
     * @return string
265
     */
266 3
    public function getUrl($path)
267
    {
268 3
        $segments = $this->parse_url($path);
269
        $query = empty($segments['query']) ? '' : '?'.$segments['query'];
270
271
        return $this->normalizeHost($this->domain).ltrim(implode('/', array_map('urlencode', explode('/', $segments['path']))), '/').$query;
272
    }
273
274
    /**
275
     * Read a file.
276
     *
277
     * @param string $path
278 1
     *
279
     * @return array|false
280 1
     */
281
    public function read($path)
282 1
    {
283
        $contents = file_get_contents($this->getUrl($path));
284
285
        return compact('contents', 'path');
286
    }
287
288
    /**
289
     * Read a file as a stream.
290
     *
291
     * @param string $path
292 1
     *
293
     * @return array|false
294 1
     */
295 1
    public function readStream($path)
296
    {
297 1
        if (ini_get('allow_url_fopen')) {
298
            $stream = fopen($this->getUrl($path), 'r');
299
300 1
            return compact('stream', 'path');
301
        }
302
303
        return false;
304
    }
305
306
    /**
307
     * List contents of a directory.
308
     *
309
     * @param string $directory
310
     * @param bool   $recursive
311 1
     *
312
     * @return array
313 1
     */
314
    public function listContents($directory = '', $recursive = false)
315 1
    {
316
        $list = [];
317 1
318 1
        $result = $this->getBucketManager()->listFiles($this->bucket, $directory);
319 1
320
        foreach (isset($result[0]['items']) ? $result[0]['items'] : [] as $files) {
321 1
            $list[] = $this->normalizeFileInfo($files);
322
        }
323
324
        return $list;
325
    }
326
327
    /**
328
     * Get all the meta data of a file or directory.
329
     *
330
     * @param string $path
331 1
     *
332
     * @return array|false
333 1
     */
334 1
    public function getMetadata($path)
335
    {
336 1
        $result = $this->getBucketManager()->stat($this->bucket, $path);
337
        $result[0]['key'] = $path;
338
339
        return $this->normalizeFileInfo($result[0]);
0 ignored issues
show
Documentation introduced by
$result[0] is of type null|object<Qiniu\Http\Error>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
340
    }
341
342
    /**
343
     * Get the size of a file.
344
     *
345
     * @param string $path
346 1
     *
347
     * @return array|false
348 1
     */
349
    public function getSize($path)
350
    {
351
        return $this->getMetadata($path);
352
    }
353
354
    /**
355
     * Fetch url to bucket.
356
     *
357
     * @param string $path
358
     * @param string $url
359
     *
360
     * @return array|false
361
     */
362
    public function fetch($path, $url)
363
    {
364
        list($response, $error) = $this->getBucketManager()->fetch($url, $this->bucket, $path);
365
366
        if ($error) {
367
            return false;
368
        }
369
370
        return $response;
371
    }
372
373
    /**
374
     * Get private file download url.
375
     *
376
     * @param string $path
377
     * @param int    $expires
378 1
     *
379
     * @return string
380 1
     */
381
    public function privateDownloadUrl($path, $expires = 3600)
382 1
    {
383
        return  $this->getAuthManager()->privateDownloadUrl($this->getUrl($path), $expires);
384
    }
385
386
    /**
387
     * Refresh file cache.
388
     *
389
     * @param string|array $path
390
     *
391
     * @return array
392 1
     */
393
    public function refresh($path)
394 1
    {
395 1
        if (is_string($path)) {
396 1
            $path = [$path];
397
        }
398
399 1
        // 将 $path 变成完整的 url
400
        $urls = array_map([$this, 'getUrl'], $path);
401 1
402
        return $this->getCdnManager()->refreshUrls($urls);
403
    }
404
405
    /**
406
     * Get the mime-type of a file.
407
     *
408
     * @param string $path
409
     *
410
     * @return array|false
411 1
     */
412
    public function getMimeType($path)
413 1
    {
414
        $response = $this->getBucketManager()->stat($this->bucket, $path);
415 1
416 1
        if (empty($response[0]['mimeType'])) {
417
            return false;
418
        }
419 1
420
        return ['mimetype' => $response[0]['mimeType']];
421
    }
422
423
    /**
424
     * Get the timestamp of a file.
425
     *
426
     * @param string $path
427
     *
428
     * @return array|false
429 1
     */
430
    public function getTimestamp($path)
431 1
    {
432
        return $this->getMetadata($path);
433
    }
434
435
    /**
436
     * @param \Qiniu\Storage\BucketManager $manager
437
     *
438
     * @return $this
439 1
     */
440
    public function setBucketManager(BucketManager $manager)
441 1
    {
442
        $this->bucketManager = $manager;
443 1
444
        return $this;
445
    }
446
447
    /**
448
     * @param \Qiniu\Storage\UploadManager $manager
449
     *
450
     * @return $this
451 1
     */
452
    public function setUploadManager(UploadManager $manager)
453 1
    {
454
        $this->uploadManager = $manager;
455 1
456
        return $this;
457
    }
458
459
    /**
460
     * @param \Qiniu\Auth $manager
461
     *
462
     * @return $this
463 1
     */
464
    public function setAuthManager(Auth $manager)
465 1
    {
466
        $this->authManager = $manager;
467 1
468
        return $this;
469
    }
470
471
    /**
472
     * @param CdnManager $manager
473
     *
474
     * @return $this
475
     */
476
    public function setCdnManager(CdnManager $manager)
477
    {
478
        $this->cdnManager = $manager;
479
480
        return $this;
481
    }
482
483
    /**
484
     * @return \Qiniu\Storage\BucketManager
485 1
     */
486
    public function getBucketManager()
487 1
    {
488
        return $this->bucketManager ?: $this->bucketManager = new BucketManager($this->getAuthManager());
489
    }
490
491
    /**
492
     * @return \Qiniu\Auth
493 1
     */
494
    public function getAuthManager()
495 1
    {
496
        return $this->authManager ?: $this->authManager = new Auth($this->accessKey, $this->secretKey);
497
    }
498
499
    /**
500
     * @return \Qiniu\Storage\UploadManager
501 1
     */
502
    public function getUploadManager()
503 1
    {
504
        return $this->uploadManager ?: $this->uploadManager = new UploadManager();
505
    }
506
507
    /**
508
     * @return \Qiniu\Cdn\CdnManager
509
     */
510
    public function getCdnManager()
511
    {
512
        return $this->cdnManager ?: $this->cdnManager = new CdnManager($this->getAuthManager());
513
    }
514
515
    /**
516
     * @return string
517
     */
518
    public function getBucket()
519
    {
520
        return $this->bucket;
521
    }
522
523
    /**
524
     * Get the upload token.
525
     *
526
     * @param string|null $key
527
     * @param int         $expires
528
     * @param string|null $policy
529
     * @param string|null $strictPolice
530
     *
531
     * @return string
532 1
     */
533
    public function getUploadToken($key = null, $expires = 3600, $policy = null, $strictPolice = null)
534 1
    {
535
        return $this->getAuthManager()->uploadToken($this->bucket, $key, $expires, $policy, $strictPolice);
0 ignored issues
show
Documentation introduced by
$strictPolice is of type string|null, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
536
    }
537
538
    /**
539
     * @param array $stats
540
     *
541
     * @return array
542 2
     */
543
    protected function normalizeFileInfo(array $stats)
544
    {
545 2
        return [
546 2
            'type' => 'file',
547 2
            'path' => $stats['key'],
548 2
            'timestamp' => floor($stats['putTime'] / 10000000),
549 2
            'size' => $stats['fsize'],
550
        ];
551
    }
552
553
    /**
554
     * @param string $domain
555
     *
556
     * @return string
557 4
     */
558
    protected function normalizeHost($domain)
559 4
    {
560 4
        if (0 !== stripos($domain, 'https://') && 0 !== stripos($domain, 'http://')) {
561 4
            $domain = "http://{$domain}";
562
        }
563 4
564
        return rtrim($domain, '/').'/';
565
    }
566
567
    /**
568
     * Does a UTF-8 safe version of PHP parse_url function
569
     *
570
     * @param   string  $url  URL to parse
571
     *
572
     * @return  mixed  Associative array or false if badly formed URL.
573
     *
574
     * @see     http://us3.php.net/manual/en/function.parse-url.php
575
     * @since   11.1
576
     */
577
    protected static function parse_url($url)
578
    {
579
        $result = false;
580
581
        // Build arrays of values we need to decode before parsing
582
        $entities = array('%21', '%2A', '%27', '%28', '%29', '%3B', '%3A', '%40', '%26', '%3D', '%24', '%2C', '%2F', '%3F', '%23', '%5B', '%5D');
583
        $replacements = array('!', '*', "'", "(", ")", ";", ":", "@", "&", "=", "$", ",", "/", "?", "#", "[", "]");
584
585
        // Create encoded URL with special URL characters decoded so it can be parsed
586
        // All other characters will be encoded
587
        $encodedURL = str_replace($entities, $replacements, urlencode($url));
588
589
        // Parse the encoded URL
590
        $encodedParts = parse_url($encodedURL);
591
592
        // Now, decode each value of the resulting array
593
        if ($encodedParts)
594
        {
595
            foreach ($encodedParts as $key => $value)
596
            {
597
                $result[$key] = urldecode(str_replace($replacements, $entities, $value));
598
            }
599
        }
600
        return $result;
601
    }
602
}
603