Passed
Push — master ( 5dcae1...4e176d )
by frey
02:33
created

Cosapi::time()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Freyo\Flysystem\QcloudCOSv4\Client;
4
5
class Cosapi
6
{
7
    //计算sign签名的时间参数
8
    const EXPIRED_SECONDS = 180;
9
    //1M
10
    const SLICE_SIZE_1M = 1048576;
11
    //20M 大于20M的文件需要进行分片传输
12
    const MAX_UNSLICE_FILE_SIZE = 20971520;
13
    //失败尝试次数
14
    const MAX_RETRY_TIMES = 3;
15
16
    //HTTP请求超时时间
17
    private static $timeout = 60;
18
    private static $region = 'gz'; // default region is guangzou
19
20
    /**
21
     * 获取当前指定时区的 Unix 时间戳
22
     *
23
     * @param string $timezone
24
     *
25
     * @return int
26
     */
27 15
    public static function time($timezone = 'Asia/Shanghai')
28
    {
29 15
        return date_create('now', timezone_open($timezone))->getTimestamp();
30
    }
31
32
    /**
33
     * 设置HTTP请求超时时间.
34
     *
35
     * @param int $timeout 超时时长
36
     *
37
     * @return bool
38
     */
39
    public static function setTimeout($timeout = 60)
40
    {
41
        if (!is_int($timeout) || $timeout < 0) {
42
            return false;
43
        }
44
45
        self::$timeout = $timeout;
46
47
        return true;
48
    }
49
50
    public static function setRegion($region)
51
    {
52
        self::$region = $region;
53
    }
54
55
    /**
56
     * 上传文件,自动判断文件大小,如果小于20M则使用普通文件上传,大于20M则使用分片上传.
57
     *
58
     * @param string $bucket     bucket名称
59
     * @param string $srcPath    本地文件路径
60
     * @param string $dstPath    上传的文件路径
61
     * @param string $bizAttr    文件属性
62
     * @param string $sliceSize  分片大小(512k,1m,2m,3m),默认:1m
63
     * @param string $insertOnly 同名文件是否覆盖
64
     *
65
     * @return array
66
     */
67 2
    public static function upload($bucket, $srcPath, $dstPath, $bizAttr = null, $sliceSize = null, $insertOnly = null)
68
    {
69 2 View Code Duplication
        if (!file_exists($srcPath)) {
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...
70
            return [
71
                'code'    => ErrorCode::COSAPI_PARAMS_ERROR,
72
                'message' => 'file '.$srcPath.' not exists',
73
                'data'    => [],
74
            ];
75
        }
76
77 2
        $dstPath = self::normalizerPath($dstPath, false);
78
79
        //文件大于20M则使用分片传输
80 2
        if (filesize($srcPath) < self::MAX_UNSLICE_FILE_SIZE) {
81 2
            return self::uploadFile($bucket, $srcPath, $dstPath, $bizAttr, $insertOnly);
82
        } else {
83
            $sliceSize = self::getSliceSize($sliceSize);
84
85
            return self::uploadBySlicing($bucket, $srcPath, $dstPath, $bizAttr, $sliceSize, $insertOnly);
86
        }
87
    }
88
89
    /**
90
     * 创建目录.
91
     *
92
     * @param string $bucket  bucket名称
93
     * @param string $folder  目录路径
94
     * @param string $bizAttr 目录属性
95
     *
96
     * @return array
97
     */
98 1
    public static function createFolder($bucket, $folder, $bizAttr = null)
99
    {
100 1
        if (!self::isValidPath($folder)) {
101
            return [
102
                'code'    => ErrorCode::COSAPI_PARAMS_ERROR,
103
                'message' => 'folder '.$folder.' is not a valid folder name',
104
                'data'    => [],
105
            ];
106
        }
107
108 1
        $folder = self::normalizerPath($folder, true);
109 1
        $folder = self::cosUrlEncode($folder);
110 1
        $expired = self::time() + self::EXPIRED_SECONDS;
111 1
        $url = self::generateResUrl($bucket, $folder);
112 1
        $signature = Auth::createReusableSignature($expired, $bucket);
113
114
        $data = [
115 1
            'op'       => 'create',
116 1
            'biz_attr' => (isset($bizAttr) ? $bizAttr : ''),
117 1
        ];
118
119 1
        $data = json_encode($data);
120
121
        $req = [
122 1
            'url'     => $url,
123 1
            'method'  => 'post',
124 1
            'timeout' => self::$timeout,
125 1
            'data'    => $data,
126
            'header'  => [
127 1
                'Authorization: '.$signature,
128 1
                'Content-Type: application/json',
129 1
            ],
130 1
        ];
131
132 1
        return self::sendRequest($req);
133
    }
134
135
    /**
136
     * 目录列表.
137
     *
138
     * @param string $bucket  bucket名称
139
     * @param string $folder  目录路径,sdk会补齐末尾的 '/'
140
     * @param int    $num     拉取的总数
141
     * @param string $pattern eListBoth,ListDirOnly,eListFileOnly  默认both
142
     * @param int    $order   默认正序(=0), 填1为反序,
143
     * @param string $context 透传字段,用于翻页,前端不需理解,需要往前/往后翻页则透传回来
144
     *
145
     * @return array
146
     */
147 1
    public static function listFolder($bucket, $folder, $num = 20, $pattern = 'eListBoth', $order = 0, $context = null)
148
    {
149 1
        $folder = self::normalizerPath($folder, true);
150
151 1
        return self::listBase($bucket, $folder, $num, $pattern, $order, $context);
152
    }
153
154
    /**
155
     * 目录列表(前缀搜索).
156
     *
157
     * @param string $bucket  bucket名称
158
     * @param string $prefix  列出含此前缀的所有文件
159
     * @param int    $num     拉取的总数
160
     * @param string $pattern eListBoth(默认),ListDirOnly,eListFileOnly
161
     * @param int    $order   默认正序(=0), 填1为反序,
162
     * @param string $context 透传字段,用于翻页,前端不需理解,需要往前/往后翻页则透传回来
163
     *
164
     * @return array
165
     */
166
    public static function prefixSearch($bucket, $prefix, $num = 20, $pattern = 'eListBoth', $order = 0, $context = null)
167
    {
168
        $path = self::normalizerPath($prefix);
169
170
        return self::listBase($bucket, $path, $num, $pattern, $order, $context);
171
    }
172
173
    /**
174
     * 目录更新.
175
     *
176
     * @param string $bucket  bucket名称
177
     * @param string $folder  文件夹路径,SDK会补齐末尾的 '/'
178
     * @param string $bizAttr 目录属性
179
     *
180
     * @return array
181
     */
182
    public static function updateFolder($bucket, $folder, $bizAttr = null)
183
    {
184
        $folder = self::normalizerPath($folder, true);
185
186
        return self::updateBase($bucket, $folder, $bizAttr);
187
    }
188
189
    /**
190
     * 查询目录信息.
191
     *
192
     * @param string $bucket bucket名称
193
     * @param string $folder 目录路径
194
     *
195
     * @return array
196
     */
197
    public static function statFolder($bucket, $folder)
198
    {
199
        $folder = self::normalizerPath($folder, true);
200
201
        return self::statBase($bucket, $folder);
202
    }
203
204
    /**
205
     * 删除目录.
206
     *
207
     * @param string $bucket bucket名称
208
     * @param string $folder 目录路径
209
     *                       注意不能删除bucket下根目录/
210
     *
211
     * @return array
212
     */
213 1 View Code Duplication
    public static function delFolder($bucket, $folder)
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...
214
    {
215 1
        if (empty($bucket) || empty($folder)) {
216
            return [
217
                'code'    => ErrorCode::COSAPI_PARAMS_ERROR,
218
                'message' => 'bucket or path is empty', ];
219
        }
220
221 1
        $folder = self::normalizerPath($folder, true);
222
223 1
        return self::delBase($bucket, $folder);
224
    }
225
226
    /**
227
     * 更新文件.
228
     *
229
     * @param string $bucket                 bucket名称
230
     * @param string $path                   文件路径
231
     * @param null   $bizAttr
232
     * @param string $authority              eInvalid(继承Bucket的读写权限)/eWRPrivate(私有读写)/eWPrivateRPublic(公有读私有写)
233
     * @param array  $customer_headers_array 携带的用户自定义头域,包括
234
     *                                       'Cache-Control' => '*'
235
     *                                       'Content-Type' => '*'
236
     *                                       'Content-Disposition' => '*'
237
     *                                       'Content-Language' => '*'
238
     *                                       'x-cos-meta-自定义内容' => '*'
239
     *
240
     * @return array
241
     */
242 1
    public static function update($bucket, $path, $bizAttr = null, $authority = null, $customer_headers_array = null)
243
    {
244 1
        $path = self::normalizerPath($path);
245
246 1
        return self::updateBase($bucket, $path, $bizAttr, $authority, $customer_headers_array);
247
    }
248
249
    /**
250
     * 查询文件信息.
251
     *
252
     * @param string $bucket bucket名称
253
     * @param string $path   文件路径
254
     *
255
     * @return array
256
     */
257 6
    public static function stat($bucket, $path)
258
    {
259 6
        $path = self::normalizerPath($path);
260
261 6
        return self::statBase($bucket, $path);
262
    }
263
264
    /**
265
     * 删除文件.
266
     *
267
     * @param string $bucket
268
     * @param string $path   文件路径
269
     *
270
     * @return array
271
     */
272 1 View Code Duplication
    public static function delFile($bucket, $path)
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...
273
    {
274 1
        if (empty($bucket) || empty($path)) {
275
            return [
276
                'code'    => ErrorCode::COSAPI_PARAMS_ERROR,
277
                'message' => 'path is empty', ];
278
        }
279
280 1
        $path = self::normalizerPath($path);
281
282 1
        return self::delBase($bucket, $path);
283
    }
284
285
    /**
286
     * 内部方法, 上传文件.
287
     *
288
     * @param string $bucket     bucket名称
289
     * @param string $srcPath    本地文件路径
290
     * @param string $dstPath    上传的文件路径
291
     * @param string $bizAttr    文件属性
292
     * @param int    $insertOnly 是否覆盖同名文件:0 覆盖,1:不覆盖
293
     *
294
     * @return array
295
     */
296 2
    private static function uploadFile($bucket, $srcPath, $dstPath, $bizAttr = null, $insertOnly = null)
297
    {
298 2
        $srcPath = realpath($srcPath);
299 2
        $dstPath = self::cosUrlEncode($dstPath);
300
301 2 View Code Duplication
        if (filesize($srcPath) >= self::MAX_UNSLICE_FILE_SIZE) {
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...
302
            return [
303
                'code'    => ErrorCode::COSAPI_PARAMS_ERROR,
304
                'message' => 'file '.$srcPath.' larger then 20M, please use uploadBySlicing interface',
305
                'data'    => [],
306
            ];
307
        }
308
309 2
        $expired = self::time() + self::EXPIRED_SECONDS;
310 2
        $url = self::generateResUrl($bucket, $dstPath);
311 2
        $signature = Auth::createReusableSignature($expired, $bucket);
312 2
        $fileSha = hash_file('sha1', $srcPath);
313
314
        $data = [
315 2
            'op'       => 'upload',
316 2
            'sha'      => $fileSha,
317 2
            'biz_attr' => (isset($bizAttr) ? $bizAttr : ''),
318 2
        ];
319
320 2
        $data['filecontent'] = file_get_contents($srcPath);
321
322 2
        if (isset($insertOnly) && strlen($insertOnly) > 0) {
323 2
            $data['insertOnly'] = (($insertOnly == 0 || $insertOnly == '0') ? 0 : 1);
324 2
        }
325
326
        $req = [
327 2
            'url'     => $url,
328 2
            'method'  => 'post',
329 2
            'timeout' => self::$timeout,
330 2
            'data'    => $data,
331
            'header'  => [
332 2
                'Authorization: '.$signature,
333 2
            ],
334 2
        ];
335
336 2
        return self::sendRequest($req);
337
    }
338
339
    /**
340
     * 内部方法,上传文件.
341
     *
342
     * @param string $bucket     bucket名称
343
     * @param string $srcFpath   本地文件路径
344
     * @param string $dstFpath   上传的文件路径
345
     * @param string $bizAttr    文件属性
346
     * @param string $sliceSize  分片大小
347
     * @param int    $insertOnly 是否覆盖同名文件:0 覆盖,1:不覆盖
348
     *
349
     * @return array
350
     */
351
    private static function uploadBySlicing($bucket, $srcFpath, $dstFpath, $bizAttr = null, $sliceSize = null, $insertOnly = null)
352
    {
353
        $srcFpath = realpath($srcFpath);
354
        $fileSize = filesize($srcFpath);
355
        $dstFpath = self::cosUrlEncode($dstFpath);
356
        $url = self::generateResUrl($bucket, $dstFpath);
357
        $sliceCount = ceil($fileSize / $sliceSize);
358
        // expiration seconds for one slice mutiply by slice count
359
        // will be the expired seconds for whole file
360
        $expiration = self::time() + (self::EXPIRED_SECONDS * $sliceCount);
361
        if ($expiration >= (self::time() + 10 * 24 * 60 * 60)) {
362
            $expiration = self::time() + 10 * 24 * 60 * 60;
363
        }
364
        $signature = Auth::createReusableSignature($expiration, $bucket);
365
366
        $sliceUploading = new SliceUploading(self::$timeout * 1000, self::MAX_RETRY_TIMES);
367
        for ($tryCount = 0; $tryCount < self::MAX_RETRY_TIMES; ++$tryCount) {
368
            if ($sliceUploading->initUploading(
369
                $signature,
370
                $srcFpath,
371
                $url,
372
                $fileSize, $sliceSize, $bizAttr, $insertOnly)
373
            ) {
374
                break;
375
            }
376
377
            $errorCode = $sliceUploading->getLastErrorCode();
378
            if ($errorCode === -4019) {
379
                // Delete broken file and retry again on _ERROR_FILE_NOT_FINISH_UPLOAD error.
380
                self::delFile($bucket, $dstFpath);
381
                continue;
382
            }
383
384 View Code Duplication
            if ($tryCount === self::MAX_RETRY_TIMES - 1) {
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...
385
                return [
386
                    'code'       => $sliceUploading->getLastErrorCode(),
387
                    'message'    => $sliceUploading->getLastErrorMessage(),
388
                    'request_id' => $sliceUploading->getRequestId(),
389
                ];
390
            }
391
        }
392
393 View Code Duplication
        if (!$sliceUploading->performUploading()) {
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...
394
            return [
395
                'code'       => $sliceUploading->getLastErrorCode(),
396
                'message'    => $sliceUploading->getLastErrorMessage(),
397
                'request_id' => $sliceUploading->getRequestId(),
398
            ];
399
        }
400
401 View Code Duplication
        if (!$sliceUploading->finishUploading()) {
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...
402
            return [
403
                'code'       => $sliceUploading->getLastErrorCode(),
404
                'message'    => $sliceUploading->getLastErrorMessage(),
405
                'request_id' => $sliceUploading->getRequestId(),
406
            ];
407
        }
408
409
        return [
410
            'code'       => 0,
411
            'message'    => 'success',
412
            'request_id' => $sliceUploading->getRequestId(),
413
            'data'       => [
414
                'access_url'    => $sliceUploading->getAccessUrl(),
415
                'resource_path' => $sliceUploading->getResourcePath(),
416
                'source_url'    => $sliceUploading->getSourceUrl(),
417
            ],
418
        ];
419
    }
420
421
    /**
422
     * 内部公共函数.
423
     *
424
     * @param string $bucket  bucket名称
425
     * @param string $path    文件夹路径
426
     * @param int    $num     拉取的总数
427
     * @param string $pattern eListBoth(默认),ListDirOnly,eListFileOnly
428
     * @param int    $order   默认正序(=0), 填1为反序,
429
     * @param string $context 在翻页查询时候用到
430
     *
431
     * @return array
432
     */
433 1
    private static function listBase($bucket, $path, $num = 20, $pattern = 'eListBoth', $order = 0, $context = null)
434
    {
435 1
        $path = self::cosUrlEncode($path);
436 1
        $expired = self::time() + self::EXPIRED_SECONDS;
437 1
        $url = self::generateResUrl($bucket, $path);
438 1
        $signature = Auth::createReusableSignature($expired, $bucket);
439
440
        $data = [
441 1
            'op' => 'list',
442 1
        ];
443
444 1
        if (self::isPatternValid($pattern) == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
445
            return [
446
                'code'    => ErrorCode::COSAPI_PARAMS_ERROR,
447
                'message' => 'parameter pattern invalid',
448
            ];
449
        }
450 1
        $data['pattern'] = $pattern;
451
452 1 View Code Duplication
        if ($order != 0 && $order != 1) {
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...
453
            return [
454
                'code'    => ErrorCode::COSAPI_PARAMS_ERROR,
455
                'message' => 'parameter order invalid',
456
            ];
457
        }
458 1
        $data['order'] = $order;
459
460 1 View Code Duplication
        if ($num < 0 || $num > 199) {
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...
461
            return [
462
                'code'    => ErrorCode::COSAPI_PARAMS_ERROR,
463
                'message' => 'parameter num invalid, num need less then 200',
464
            ];
465
        }
466 1
        $data['num'] = $num;
467
468 1
        if (isset($context)) {
469
            $data['context'] = $context;
470
        }
471
472 1
        $url = $url.'?'.http_build_query($data);
473
474
        $req = [
475 1
            'url'     => $url,
476 1
            'method'  => 'get',
477 1
            'timeout' => self::$timeout,
478
            'header'  => [
479 1
                'Authorization: '.$signature,
480 1
            ],
481 1
        ];
482
483 1
        return self::sendRequest($req);
484
    }
485
486
    /**
487
     * 内部公共方法(更新文件和更新文件夹).
488
     *
489
     * @param string $bucket               bucket名称
490
     * @param string $path                 路径
491
     * @param string $bizAttr              文件/目录属性
492
     * @param string $authority            eInvalid/eWRPrivate(私有)/eWPrivateRPublic(公有读写)
493
     * @param array  $custom_headers_array 携带的用户自定义头域,包括
494
     *                                     'Cache-Control' => '*'
495
     *                                     'Content-Type' => '*'
496
     *                                     'Content-Disposition' => '*'
497
     *                                     'Content-Language' => '*'
498
     *                                     'x-cos-meta-自定义内容' => '*'
499
     *
500
     * @return array
501
     */
502 1
    private static function updateBase(
503
        $bucket, $path, $bizAttr = null, $authority = null, $custom_headers_array = null)
504
    {
505 1
        $path = self::cosUrlEncode($path);
506
507 1
        $url = self::generateResUrl($bucket, $path);
508 1
        $signature = Auth::createNonreusableSignature($bucket, $path);
509
510 1
        $data = ['op' => 'update'];
511
512 1
        if (isset($bizAttr)) {
513
            $data['biz_attr'] = $bizAttr;
514
        }
515
516 1
        if (isset($authority) && strlen($authority) > 0) {
517 1
            if (self::isAuthorityValid($authority) == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
518
                return [
519
                    'code'    => ErrorCode::COSAPI_PARAMS_ERROR,
520
                    'message' => 'parameter authority invalid', ];
521
            }
522
523 1
            $data['authority'] = $authority;
524 1
        }
525
526 1
        if (isset($custom_headers_array)) {
527
            $data['custom_headers'] = [];
528
            self::add_customer_header($data['custom_headers'], $custom_headers_array);
529
        }
530
531 1
        $data = json_encode($data);
532
533
        $req = [
534 1
            'url'     => $url,
535 1
            'method'  => 'post',
536 1
            'timeout' => self::$timeout,
537 1
            'data'    => $data,
538
            'header'  => [
539 1
                'Authorization: '.$signature,
540 1
                'Content-Type: application/json',
541 1
            ],
542 1
        ];
543
544 1
        return self::sendRequest($req);
545
    }
546
547
    /**
548
     * 内部方法.
549
     *
550
     * @param string $bucket bucket名称
551
     * @param string $path   文件/目录路径
552
     *
553
     * @return array
554
     */
555 6
    private static function statBase($bucket, $path)
556
    {
557 6
        $path = self::cosUrlEncode($path);
558 6
        $expired = self::time() + self::EXPIRED_SECONDS;
559 6
        $url = self::generateResUrl($bucket, $path);
560 6
        $signature = Auth::createReusableSignature($expired, $bucket);
561
562 6
        $data = ['op' => 'stat'];
563
564 6
        $url = $url.'?'.http_build_query($data);
565
566
        $req = [
567 6
            'url'     => $url,
568 6
            'method'  => 'get',
569 6
            'timeout' => self::$timeout,
570
            'header'  => [
571 6
                'Authorization: '.$signature,
572 6
            ],
573 6
        ];
574
575 6
        return self::sendRequest($req);
576
    }
577
578
    /**
579
     * 内部私有方法.
580
     *
581
     * @param string $bucket bucket名称
582
     * @param string $path   文件/目录路径路径
583
     *
584
     * @return array
585
     */
586 2
    private static function delBase($bucket, $path)
587
    {
588 2
        if ($path == '/') {
589
            return [
590
                'code'    => ErrorCode::COSAPI_PARAMS_ERROR,
591
                'message' => 'can not delete bucket using api! go to '.
592
                    'http://console.qcloud.com/cos to operate bucket', ];
593
        }
594
595 2
        $path = self::cosUrlEncode($path);
596
597 2
        $url = self::generateResUrl($bucket, $path);
598 2
        $signature = Auth::createNonreusableSignature($bucket, $path);
599
600 2
        $data = ['op' => 'delete'];
601
602 2
        $data = json_encode($data);
603
604
        $req = [
605 2
            'url'     => $url,
606 2
            'method'  => 'post',
607 2
            'timeout' => self::$timeout,
608 2
            'data'    => $data,
609
            'header'  => [
610 2
                'Authorization: '.$signature,
611 2
                'Content-Type: application/json',
612 2
            ],
613 2
        ];
614
615 2
        return self::sendRequest($req);
616
    }
617
618
    /**
619
     * 内部公共方法, 路径编码
620
     *
621
     * @param string $path 待编码路径
622
     *
623
     * @return string
624
     */
625 13
    private static function cosUrlEncode($path)
626
    {
627 13
        return str_replace('%2F', '/', rawurlencode($path));
628
    }
629
630
    /**
631
     * 内部公共方法, 构造URL.
632
     *
633
     * @param string $bucket
634
     * @param string $dstPath
635
     *
636
     * @return string
637
     */
638 15
    private static function generateResUrl($bucket, $dstPath)
639
    {
640 15
        $endPoint = Conf::API_COSAPI_END_POINT;
641 15
        $endPoint = str_replace('region', self::$region, $endPoint);
642
643 15
        return $endPoint.Conf::getAppId().'/'.$bucket.$dstPath;
644
    }
645
646
    /**
647
     * 内部公共方法, 发送消息.
648
     *
649
     * @param array $req
650
     *
651
     * @return array
652
     */
653 15
    private static function sendRequest($req)
654
    {
655 15
        $rsp = HttpClient::sendRequest($req);
656 15
        if ($rsp === false) {
657
            return [
658
                'code'    => ErrorCode::COSAPI_NETWORK_ERROR,
659
                'message' => 'network error',
660
            ];
661
        }
662
663 15
        $ret = json_decode($rsp, true);
664
665 15
        if ($ret === null) {
666
            return [
667 15
                'code'    => ErrorCode::COSAPI_NETWORK_ERROR,
668 15
                'message' => $rsp,
669 15
                'data'    => [],
670 15
            ];
671
        }
672
673
        return $ret;
674
    }
675
676
    /**
677
     * Get slice size.
678
     *
679
     * @param string $sliceSize
680
     *
681
     * @return int
682
     */
683
    private static function getSliceSize($sliceSize)
684
    {
685
        $sliceSize = (int) $sliceSize;
686
687
        switch ($sliceSize) {
688
            case 512:
689
                $sliceSize = 0.5 * self::SLICE_SIZE_1M;
690
                break;
691
            case 1:
692
                $sliceSize = 1 * self::SLICE_SIZE_1M;
693
                break;
694
            case 2:
695
                $sliceSize = 2 * self::SLICE_SIZE_1M;
696
                break;
697
            case 3:
698
                $sliceSize = 3 * self::SLICE_SIZE_1M;
699
                break;
700
            default:
701
                // Fix slice size to 1MB.
702
                $sliceSize = self::SLICE_SIZE_1M;
703
        }
704
705
        return $sliceSize;
706
    }
707
708
    /**
709
     * 内部方法, 规整文件路径.
710
     *
711
     * @param string $path     文件路径
712
     * @param bool   $isfolder 是否为文件夹
713
     *
714
     * @return string
715
     */
716 15
    private static function normalizerPath($path, $isfolder = false)
717
    {
718 15
        if (preg_match('/^\//', $path) == 0) {
719 15
            $path = '/'.$path;
720 15
        }
721
722 15
        if ($isfolder === true) {
723 3
            if (preg_match('/\/$/', $path) == 0) {
724 3
                $path = $path.'/';
725 3
            }
726 3
        }
727
728
        // Remove unnecessary slashes.
729 15
        $path = preg_replace('#/+#', '/', $path);
730
731 15
        return $path;
732
    }
733
734
    /**
735
     * 判断authority值是否正确.
736
     *
737
     * @param string $authority
738
     *
739
     * @return bool
740
     */
741 1
    private static function isAuthorityValid($authority)
742
    {
743 1
        if ($authority == 'eInvalid' || $authority == 'eWRPrivate' || $authority == 'eWPrivateRPublic') {
744 1
            return true;
745
        }
746
747
        return false;
748
    }
749
750
    /**
751
     * 判断pattern值是否正确.
752
     *
753
     * @param string $pattern
754
     *
755
     * @return bool
756
     */
757 1
    private static function isPatternValid($pattern)
758
    {
759 1
        if ($pattern == 'eListBoth' || $pattern == 'eListDirOnly' || $pattern == 'eListFileOnly') {
760 1
            return true;
761
        }
762
763
        return false;
764
    }
765
766
    /**
767
     * 判断是否符合自定义属性.
768
     *
769
     * @param string $key
770
     *
771
     * @return bool
772
     */
773
    private static function isCustomer_header($key)
774
    {
775
        if ($key == 'Cache-Control' || $key == 'Content-Type' ||
776
            $key == 'Content-Disposition' || $key == 'Content-Language' ||
777
            $key == 'Content-Encoding' ||
778
            substr($key, 0, strlen('x-cos-meta-')) == 'x-cos-meta-'
779
        ) {
780
            return true;
781
        }
782
783
        return false;
784
    }
785
786
    /**
787
     * 增加自定义属性到data中.
788
     *
789
     * @param array $data
790
     * @param array $customer_headers_array
791
     */
792
    private static function add_customer_header(&$data, &$customer_headers_array)
793
    {
794
        if (count($customer_headers_array) < 1) {
795
            return;
796
        }
797
        foreach ($customer_headers_array as $key => $value) {
798
            if (self::isCustomer_header($key)) {
799
                $data[$key] = $value;
800
            }
801
        }
802
    }
803
804
    // Check |$path| is a valid file path.
805
    // Return true on success, otherwise return false.
806
807
    /**
808
     * @param string $path
809
     */
810 1
    private static function isValidPath($path)
811
    {
812 1
        if (strpos($path, '?') !== false) {
813
            return false;
814
        }
815 1
        if (strpos($path, '*') !== false) {
816
            return false;
817
        }
818 1
        if (strpos($path, ':') !== false) {
819
            return false;
820
        }
821 1
        if (strpos($path, '|') !== false) {
822
            return false;
823
        }
824 1
        if (strpos($path, '\\') !== false) {
825
            return false;
826
        }
827 1
        if (strpos($path, '<') !== false) {
828
            return false;
829
        }
830 1
        if (strpos($path, '>') !== false) {
831
            return false;
832
        }
833 1
        if (strpos($path, '"') !== false) {
834
            return false;
835
        }
836
837 1
        return true;
838
    }
839
840
    /**
841
     * Copy a file.
842
     *
843
     * @param string $bucket    bucket name.
844
     * @param string $srcFpath  source file path.
845
     * @param string $dstFpath  destination file path.
846
     * @param bool   $overwrite if the destination location is occupied, overwrite it or not?
847
     *
848
     * @return array|mixed.
0 ignored issues
show
Documentation introduced by
The doc-type array|mixed. could not be parsed: Unknown type name "mixed." at position 6. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
849
     */
850 1 View Code Duplication
    public static function copyFile($bucket, $srcFpath, $dstFpath, $overwrite = false)
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...
851
    {
852 1
        $srcFpath = self::normalizerPath($srcFpath);
853 1
        $dstFpath = self::normalizerPath($dstFpath);
854
855 1
        $url = self::generateResUrl($bucket, $srcFpath);
856 1
        $sign = Auth::createNonreusableSignature($bucket, $srcFpath);
857
        $data = [
858 1
            'op'            => 'copy',
859 1
            'dest_fileid'   => $dstFpath,
860 1
            'to_over_write' => $overwrite ? 1 : 0,
861 1
        ];
862
        $req = [
863 1
            'url'     => $url,
864 1
            'method'  => 'post',
865 1
            'timeout' => self::$timeout,
866 1
            'data'    => $data,
867
            'header'  => [
868 1
                'Authorization: '.$sign,
869 1
            ],
870 1
        ];
871
872 1
        return self::sendRequest($req);
873
    }
874
875
    /**
876
     * Move a file.
877
     *
878
     * @param string $bucket    bucket name.
879
     * @param string $srcFpath  source file path.
880
     * @param string $dstFpath  destination file path.
881
     * @param bool   $overwrite if the destination location is occupied, overwrite it or not?
882
     *
883
     * @return array
884
     */
885 1 View Code Duplication
    public static function moveFile($bucket, $srcFpath, $dstFpath, $overwrite = false)
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...
886
    {
887 1
        $srcFpath = self::normalizerPath($srcFpath);
888 1
        $dstFpath = self::normalizerPath($dstFpath);
889
890 1
        $url = self::generateResUrl($bucket, $srcFpath);
891 1
        $sign = Auth::createNonreusableSignature($bucket, $srcFpath);
892
        $data = [
893 1
            'op'            => 'move',
894 1
            'dest_fileid'   => $dstFpath,
895 1
            'to_over_write' => $overwrite ? 1 : 0,
896 1
        ];
897
        $req = [
898 1
            'url'     => $url,
899 1
            'method'  => 'post',
900 1
            'timeout' => self::$timeout,
901 1
            'data'    => $data,
902
            'header'  => [
903 1
                'Authorization: '.$sign,
904 1
            ],
905 1
        ];
906
907 1
        return self::sendRequest($req);
908
    }
909
}
910