Passed
Push — master ( adb06a...c828b5 )
by frey
39s
created

Adapter::readStream()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 2
1
<?php
2
3
namespace Freyo\Flysystem\QcloudCOSv4;
4
5
use Freyo\Flysystem\QcloudCOSv4\Client\Conf;
6
use Freyo\Flysystem\QcloudCOSv4\Client\Cosapi;
7
use Freyo\Flysystem\QcloudCOSv4\Exceptions\RuntimeException;
8
use League\Flysystem\Adapter\AbstractAdapter;
9
use League\Flysystem\AdapterInterface;
10
use League\Flysystem\Config;
11
use League\Flysystem\Util;
12
13
/**
14
 * Class Adapter.
15
 */
16
class Adapter extends AbstractAdapter
17
{
18
    /**
19
     * @var
20
     */
21
    protected $bucket;
22
23
    /**
24
     * @var
25
     */
26
    protected $debug;
27
28
    /**
29
     * Adapter constructor.
30
     *
31
     * @param $config
32
     */
33
    public function __construct($config)
34
    {
35
        Conf::setAppId($config['app_id']);
36
        Conf::setSecretId($config['secret_id']);
37
        Conf::setSecretKey($config['secret_key']);
38
39
        $this->bucket = $config['bucket'];
40
        $this->debug = $config['debug'];
41
42
        $this->setPathPrefix($config['protocol'].'://'.$config['domain'].'/');
43
44
        Cosapi::setTimeout($config['timeout']);
45
        Cosapi::setRegion($config['region']);
46
    }
47
48
    /**
49
     * @return mixed
50
     */
51 15
    public function getBucket()
52
    {
53 15
        return $this->bucket;
54
    }
55
56
    /**
57
     * @param $path
58
     *
59
     * @return string
60
     */
61 1
    public function getUrl($path)
62
    {
63 1
        return $this->applyPathPrefix($path);
64
    }
65
66
    /**
67
     * @param string $path
68
     * @param string $contents
69
     * @param Config $config
70
     *
71
     * @throws RuntimeException
72
     *
73
     * @return array|false
74
     */
75 View Code Duplication
    public function write($path, $contents, Config $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...
76
    {
77
        $tmpfname = $this->writeTempFile($contents);
78
79
        try {
80
            $response = Cosapi::upload($this->getBucket(), $tmpfname, $path,
0 ignored issues
show
Security Bug introduced by
It seems like $tmpfname defined by $this->writeTempFile($contents) on line 77 can also be of type false; however, Freyo\Flysystem\QcloudCO...Client\Cosapi::upload() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
81
                                       null, null, $config->get('insertOnly', 1));
82
83
            $this->deleteTempFile($tmpfname);
84
85
            $response = $this->normalizeResponse($response);
86
87
            if (false === $response) {
88
                return false;
89
            }
90
91
            $this->setContentType($path, $contents);
92
        } catch (RuntimeException $exception) {
93
            $this->deleteTempFile($tmpfname);
94
95
            throw $exception;
96
        }
97
98
        return $response;
99
    }
100
101
    /**
102
     * @param string   $path
103
     * @param resource $resource
104
     * @param Config   $config
105
     *
106
     * @throws RuntimeException
107
     *
108
     * @return array|false
109
     */
110 1 View Code Duplication
    public function writeStream($path, $resource, Config $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...
111
    {
112 1
        $uri = stream_get_meta_data($resource)['uri'];
113
114 1
        $response = Cosapi::upload($this->getBucket(), $uri, $path,
115 1
                                   null, null, $config->get('insertOnly', 1));
116
117 1
        $response = $this->normalizeResponse($response);
118
119
        if (false === $response) {
120
            return false;
121
        }
122
123
        $this->setContentType($path, stream_get_contents($resource));
124
125
        return $response;
126
    }
127
128
    /**
129
     * @param string $path
130
     * @param string $contents
131
     * @param Config $config
132
     *
133
     * @throws RuntimeException
134
     *
135
     * @return array|false
136
     */
137 View Code Duplication
    public function update($path, $contents, Config $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...
138
    {
139
        $tmpfname = $this->writeTempFile($contents);
140
141
        try {
142
            $response = Cosapi::upload($this->getBucket(), $tmpfname, $path,
0 ignored issues
show
Security Bug introduced by
It seems like $tmpfname defined by $this->writeTempFile($contents) on line 139 can also be of type false; however, Freyo\Flysystem\QcloudCO...Client\Cosapi::upload() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
143
                                       null, null, $config->get('insertOnly', 0));
144
145
            $this->deleteTempFile($tmpfname);
146
147
            $response = $this->normalizeResponse($response);
148
149
            if (false === $response) {
150
                return false;
151
            }
152
153
            $this->setContentType($path, $contents);
154
        } catch (RuntimeException $exception) {
155
            $this->deleteTempFile($tmpfname);
156
157
            throw $exception;
158
        }
159
160
        return $response;
161
    }
162
163
    /**
164
     * @param string   $path
165
     * @param resource $resource
166
     * @param Config   $config
167
     *
168
     * @throws RuntimeException
169
     *
170
     * @return array|false
171
     */
172 1 View Code Duplication
    public function updateStream($path, $resource, Config $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...
173
    {
174 1
        $uri = stream_get_meta_data($resource)['uri'];
175
176 1
        $response = Cosapi::upload($this->getBucket(), $uri, $path,
177 1
                                   null, null, $config->get('insertOnly', 0));
178
179 1
        $response = $this->normalizeResponse($response);
180
181
        if (false === $response) {
182
            return false;
183
        }
184
185
        $this->setContentType($path, stream_get_contents($resource));
186
187
        return $response;
188
    }
189
190
    /**
191
     * @param string $path
192
     * @param string $newpath
193
     *
194
     * @return bool
195
     */
196 1
    public function rename($path, $newpath)
197
    {
198 1
        return $this->normalizeResponse(
199 1
            Cosapi::moveFile($this->getBucket(), $path, $newpath, 1)
0 ignored issues
show
Documentation introduced by
1 is of type integer, 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...
200 1
        );
201
    }
202
203
    /**
204
     * @param string $path
205
     * @param string $newpath
206
     *
207
     * @return bool
208
     */
209 1
    public function copy($path, $newpath)
210
    {
211 1
        return $this->normalizeResponse(
212 1
            Cosapi::copyFile($this->getBucket(), $path, $newpath, 1)
0 ignored issues
show
Documentation introduced by
1 is of type integer, 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...
213 1
        );
214
    }
215
216
    /**
217
     * @param string $path
218
     *
219
     * @return bool
220
     */
221 1
    public function delete($path)
222
    {
223 1
        return $this->normalizeResponse(
224 1
            Cosapi::delFile($this->getBucket(), $path)
225 1
        );
226
    }
227
228
    /**
229
     * @param string $dirname
230
     *
231
     * @return bool
232
     */
233 1
    public function deleteDir($dirname)
234
    {
235 1
        return $this->normalizeResponse(
236 1
            Cosapi::delFolder($this->getBucket(), $dirname)
237 1
        );
238
    }
239
240
    /**
241
     * @param string $dirname
242
     * @param Config $config
243
     *
244
     * @return bool
245
     */
246 1
    public function createDir($dirname, Config $config)
247
    {
248 1
        return $this->normalizeResponse(
249 1
            Cosapi::createFolder($this->getBucket(), $dirname)
250 1
        );
251
    }
252
253
    /**
254
     * @param string $path
255
     * @param string $visibility
256
     *
257
     * @return bool
258
     */
259 1
    public function setVisibility($path, $visibility)
260
    {
261 1
        $visibility = $visibility === AdapterInterface::VISIBILITY_PUBLIC ? 'eWPrivateRPublic' : 'eWRPrivate';
262
263 1
        return $this->normalizeResponse(
264 1
            Cosapi::update($this->getBucket(), $path, null, $visibility)
265 1
        );
266
    }
267
268
    /**
269
     * @param string $path
270
     *
271
     * @return bool
272
     */
273 1
    public function has($path)
274
    {
275
        try {
276 1
            return (bool) $this->getMetadata($path);
277 1
        } catch (RuntimeException $exception) {
278 1
            return false;
279
        }
280
    }
281
282
    /**
283
     * @param string $path
284
     *
285
     * @return array
286
     */
287
    public function read($path)
288
    {
289
        return ['contents' => file_get_contents($this->getUrl($path))];
290
    }
291
292
    /**
293
     * @param string $path
294
     *
295
     * @return array
296
     */
297
    public function readStream($path)
298
    {
299
        return ['stream' => fopen($this->getUrl($path), 'r')];
300
    }
301
302
    /**
303
     * @param string $directory
304
     * @param bool   $recursive
305
     *
306
     * @return array|bool
307
     */
308 1
    public function listContents($directory = '', $recursive = false)
309
    {
310 1
        return $this->normalizeResponse(
311 1
            Cosapi::listFolder($this->getBucket(), $directory)
312 1
        );
313
    }
314
315
    /**
316
     * @param string $path
317
     *
318
     * @return array|bool
319
     */
320 6
    public function getMetadata($path)
321
    {
322 6
        return $this->normalizeResponse(
323 6
            Cosapi::stat($this->getBucket(), $path)
324 6
        );
325
    }
326
327
    /**
328
     * @param string $path
329
     *
330
     * @return array
331
     */
332 1
    public function getSize($path)
333
    {
334 1
        $stat = $this->getMetadata($path);
335
336
        if ($stat) {
337
            return ['size' => $stat['filesize']];
338
        }
339
340
        return ['size' => 0];
341
    }
342
343
    /**
344
     * @param string $path
345
     *
346
     * @return array
347
     */
348 1
    public function getMimetype($path)
349
    {
350 1
        $stat = $this->getMetadata($path);
351
352
        if ($stat && !empty($stat['custom_headers']) && !empty($stat['custom_headers']['Content-Type'])) {
353
            return ['mimetype' => $stat['custom_headers']['Content-Type']];
354
        }
355
356
        return ['mimetype' => ''];
357
    }
358
359
    /**
360
     * @param string $path
361
     *
362
     * @return array
363
     */
364 1
    public function getTimestamp($path)
365
    {
366 1
        $stat = $this->getMetadata($path);
367
368
        if ($stat) {
369
            return ['timestamp' => $stat['ctime']];
370
        }
371
372
        return ['timestamp' => 0];
373
    }
374
375
    /**
376
     * @param string $path
377
     *
378
     * @return array
379
     */
380 1
    public function getVisibility($path)
381
    {
382 1
        $stat = $this->getMetadata($path);
383
384
        $visibility = AdapterInterface::VISIBILITY_PRIVATE;
385
386
        if ($stat && $stat['authority'] === 'eWPrivateRPublic') {
387
            $visibility = AdapterInterface::VISIBILITY_PUBLIC;
388
        }
389
390
        return ['visibility' => $visibility];
391
    }
392
393
    /**
394
     * @param $content
395
     *
396
     * @return string|false
397
     */
398
    private function writeTempFile($content)
399
    {
400
        $tmpfname = tempnam('/tmp', 'dir');
401
402
        chmod($tmpfname, 0777);
403
404
        file_put_contents($tmpfname, $content);
405
406
        return $tmpfname;
407
    }
408
409
    /**
410
     * @param $tmpfname
411
     *
412
     * @return bool
413
     */
414
    private function deleteTempFile($tmpfname)
415
    {
416
        return unlink($tmpfname);
417
    }
418
419
    /**
420
     * @param $path
421
     * @param $content
422
     *
423
     * @return bool
424
     */
425
    protected function setContentType($path, $content)
426
    {
427
        $custom_headers = [
428
            'Content-Type' => Util::guessMimeType($path, $content),
429
        ];
430
431
        return $this->normalizeResponse(
432
            Cosapi::update($this->getBucket(), $path, null, null, $custom_headers)
433
        );
434
    }
435
436
    /**
437
     * @param $response
438
     *
439
     * @throws RuntimeException
440
     *
441
     * @return mixed
442
     */
443 15
    protected function normalizeResponse($response)
444
    {
445 15
        if ($response['code'] == 0) {
446
            return isset($response['data']) ? $response['data'] : true;
447
        }
448
449 15
        if ($this->debug) {
450 15
            throw new RuntimeException($response['message'], $response['code']);
451
        }
452
453
        return false;
454
    }
455
}
456