Passed
Push — master ( 717b53...e83d3e )
by alpha
19:13
created

AliyunOssAdapter::getMetadata()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13

Duplication

Lines 13
Ratio 100 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 13
loc 13
ccs 0
cts 7
cp 0
rs 9.8333
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 6
1
<?php
2
3
namespace AlphaSnow\AliyunOss;
4
5
use Carbon\Carbon;
6
use League\Flysystem\Adapter\AbstractAdapter;
7
use League\Flysystem\Adapter\CanOverwriteFiles;
8
use League\Flysystem\AdapterInterface;
9
use League\Flysystem\Config;
10
use League\Flysystem\Util;
11
use League\Flysystem\FileNotFoundException;
12
use OSS\Core\OssException;
13
use OSS\OssClient;
14
use Illuminate\Support\Facades\Log;
15
16
class AliyunOssAdapter extends AbstractAdapter implements CanOverwriteFiles
17
{
18
    /**
19
     * @var bool
20
     */
21
    protected $debug;
22
    /**
23
     * @var array
24
     */
25
    protected static $resultMap = [
26
        'Body' => 'raw_contents',
27
        'Content-Length' => 'size',
28
        'ContentType' => 'mimetype',
29
        'Size' => 'size',
30
        'StorageClass' => 'storage_class',
31
    ];
32
    /**
33
     * @var array
34
     */
35
    protected static $metaOptions = [
36
        'CacheControl',
37
        'Expires',
38
        'ServerSideEncryption',
39
        'Metadata',
40
        'ACL',
41
        'ContentType',
42
        'ContentDisposition',
43
        'ContentLanguage',
44
        'ContentEncoding',
45
    ];
46
47
    /**
48
     * @var string[]
49
     */
50
    protected static $metaMap = [
51
        'CacheControl' => 'Cache-Control',
52
        'Expires' => 'Expires',
53
        'ServerSideEncryption' => 'x-oss-server-side-encryption',
54
        'Metadata' => 'x-oss-metadata-directive',
55
        'ACL' => 'x-oss-object-acl',
56
        'ContentType' => 'Content-Type',
57
        'ContentDisposition' => 'Content-Disposition',
58
        'ContentLanguage' => 'response-content-language',
59
        'ContentEncoding' => 'Content-Encoding',
60
    ];
61
62
    /**
63
     * @var OssClient
64
     */
65
    protected $client;
66
    /**
67
     * @var string
68
     */
69
    protected $bucket;
70
    /**
71
     * @var string
72
     */
73
    protected $endPoint;
74
75
    /**
76
     * @var string
77
     */
78
    protected $cdnDomain;
79
80
    /**
81
     * @var bool
82
     */
83
    protected $ssl;
84
85
    /**
86
     * @var bool
87
     */
88
    protected $isCname;
89
90
    /**
91
     * @var array
92
     */
93
    protected $options = [
94
//        'Multipart' => 128
95
    ];
96
97
    /**
98
     * AliyunOssAdapter constructor.
99
     * @param OssClient $client
100
     * @param AliyunOssConfig $config
101
     * @param array $options
102
     */
103 2
    public function __construct(
104
        OssClient $client,
105
        AliyunOssConfig $config,
106
        array $options = []
107
    ) {
108 2
        $this->client = $client;
109 2
        $this->debug = $config->isDebug();
110 2
        $this->bucket = $config->getBucket();
111 2
        $this->endPoint = $config->getEndpoint();
112 2
        $this->ssl = $config->isSsl();
113 2
        $this->isCname = $config->isCname();
114 2
        $this->cdnDomain = $config->getCdnDomain();
115 2
        $this->options = array_merge($this->options, $options);
116 2
    }
117
118
    /**
119
     * {@inheritdoc}
120
     */
121 3 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...
122
    {
123 3
        $object = $this->applyPathPrefix($path);
124 3
        $options = $this->getOptions([], $config);
125
126 3
        if (!isset($options[OssClient::OSS_LENGTH])) {
127 3
            $options[OssClient::OSS_LENGTH] = Util::contentSize($contents);
128
        }
129 3
        if (!isset($options[OssClient::OSS_CONTENT_TYPE])) {
130 3
            $options[OssClient::OSS_CONTENT_TYPE] = Util::guessMimeType($path, $contents);
131
        }
132
133
        try {
134
            // https://help.aliyun.com/document_detail/31978.html
135 3
            $this->client->putObject($this->bucket, $object, $contents, $options);
136
        } catch (OssException $e) {
137
            $this->logErr(__FUNCTION__, $e);
138
            return false;
139
        }
140
141 3
        return $this->normalizeResponse($options, $path);
142
    }
143
144
    /**
145
     * {@inheritdoc}
146
     */
147 1
    public function writeStream($path, $resource, Config $config)
148
    {
149 1
        $object = $this->applyPathPrefix($path);
150 1
        $options = $this->getOptions([], $config);
151
152
        try {
153
            // https://help.aliyun.com/document_detail/31959.html
154 1
            $this->client->uploadStream($this->bucket, $object, $resource, $options);
155
        } catch (OssException $e) {
156
            $this->logErr(__FUNCTION__, $e);
157
            return false;
158
        }
159
160 1
        return $this->normalizeResponse($options, $path);
161
    }
162
163
    /**
164
     * {@inheritdoc}
165
     */
166 1 View Code Duplication
    public function writeFile($path, $filePath, 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...
167
    {
168 1
        $object = $this->applyPathPrefix($path);
169 1
        $options = $this->getOptions([], $config);
170
171 1
        if (!isset($options[OssClient::OSS_CONTENT_TYPE])) {
172 1
            $options[OssClient::OSS_CHECK_MD5] = true;
173
        }
174 1
        if (!isset($options[OssClient::OSS_CONTENT_TYPE])) {
175 1
            $options[OssClient::OSS_CONTENT_TYPE] = Util::guessMimeType($path, '');
176
        }
177
178
        try {
179 1
            $this->client->uploadFile($this->bucket, $object, $filePath, $options);
180
        } catch (OssException $e) {
181
            $this->logErr(__FUNCTION__, $e);
182
            return false;
183
        }
184
185 1
        return $this->normalizeResponse($options, $path);
186
    }
187
188
    /**
189
     * {@inheritdoc}
190
     */
191 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...
192
    {
193
        if (!$config->has('visibility') && !$config->has('ACL')) {
194
            // 新文件未配置权限情况下,继承旧文件权限
195
            $config->set(static::$metaMap['ACL'], $this->getObjectACL($path));
196
        }
197
        // 允许覆盖同名文件
198
        $config->set('x-oss-forbid-overwrite','false');
199
200
        return $this->write($path, $contents, $config);
201
    }
202
203
    /**
204
     * {@inheritdoc}
205
     */
206 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...
207
    {
208
        if (!$config->has('visibility') && !$config->has('ACL')) {
209
            // 新文件未配置权限情况下,继承旧文件权限
210
            $config->set(static::$metaMap['ACL'], $this->getObjectACL($path));
211
        }
212
        // 允许覆盖同名文件
213
        $config->set('x-oss-forbid-overwrite','false');
214
215
        return $this->writeStream($path, $resource, $config);
216
    }
217
218
    /**
219
     * {@inheritdoc}
220
     */
221
    public function rename($path, $newpath)
222
    {
223
        if (!$this->copy($path, $newpath)) {
224
            return false;
225
        }
226
227
        return $this->delete($path);
228
    }
229
230
    /**
231
     * {@inheritdoc}
232
     */
233 View Code Duplication
    public function copy($path, $newpath)
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...
234
    {
235
        $object = $this->applyPathPrefix($path);
236
        $newObject = $this->applyPathPrefix($newpath);
237
238
        try {
239
            $this->client->copyObject($this->bucket, $object, $this->bucket, $newObject);
240
        } catch (OssException $e) {
241
            $this->logErr(__FUNCTION__, $e);
242
            return false;
243
        }
244
245
        return true;
246
    }
247
248
    /**
249
     * {@inheritdoc}
250
     */
251 View Code Duplication
    public function delete($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...
252
    {
253
        $bucket = $this->bucket;
254
        $object = $this->applyPathPrefix($path);
255
256
        try {
257
            $this->client->deleteObject($bucket, $object);
258
        } catch (OssException $e) {
259
            $this->logErr(__FUNCTION__, $e);
260
            return false;
261
        }
262
263
        return !$this->has($path);
264
    }
265
266
    /**
267
     * {@inheritdoc}
268
     */
269
    public function deleteDir($dirname)
270
    {
271
        $dirname = rtrim($this->applyPathPrefix($dirname), '/') . '/';
272
        $dirObjects = $this->listDirObjects($dirname, true);
273
274
        if (count($dirObjects['objects']) > 0) {
275
            $objects = [];
276
            foreach ($dirObjects['objects'] as $object) {
277
                $objects[] = $object['Key'];
278
            }
279
280
            try {
281
                $this->client->deleteObjects($this->bucket, $objects);
282
            } catch (OssException $e) {
283
                $this->logErr(__FUNCTION__, $e);
284
                return false;
285
            }
286
        }
287
288
        try {
289
            $this->client->deleteObject($this->bucket, $dirname);
290
        } catch (OssException $e) {
291
            $this->logErr(__FUNCTION__, $e);
292
            return false;
293
        }
294
295
        return true;
296
    }
297
298
    /**
299
     * {@inheritdoc}
300
     */
301
    public function createDir($dirname, Config $config)
302
    {
303
        $object = $this->applyPathPrefix($dirname);
304
        $options = $this->getOptionsFromConfig($config);
305
306
        try {
307
            $this->client->createObjectDir($this->bucket, $object, $options);
308
        } catch (OssException $e) {
309
            $this->logErr(__FUNCTION__, $e);
310
            return false;
311
        }
312
313
        return ['path' => $dirname, 'type' => 'dir'];
314
    }
315
316
    /**
317
     * {@inheritdoc}
318
     */
319
    public function setVisibility($path, $visibility)
320
    {
321
        $object = $this->applyPathPrefix($path);
322
        $acl = ($visibility === AdapterInterface::VISIBILITY_PUBLIC) ? OssClient::OSS_ACL_TYPE_PUBLIC_READ : OssClient::OSS_ACL_TYPE_PRIVATE;
323
324
        $this->client->putObjectAcl($this->bucket, $object, $acl);
325
326
        return compact('visibility');
327
    }
328
329
    /**
330
     * 列举文件夹内文件列表;可递归获取子文件夹;
331
     * @param string $dirname 目录
332
     * @param bool $recursive 是否递归
333
     * @return mixed
334
     * @throws OssException
335
     */
336
    public function listDirObjects($dirname = '', $recursive = false)
337
    {
338
        $delimiter = '/';
339
        $nextMarker = '';
340
        $maxkeys = 1000;
341
342
        //存储结果
343
        $result = [];
344
345
        while (true) {
346
            $options = [
347
                'delimiter' => $delimiter,
348
                'prefix' => $dirname,
349
                'max-keys' => $maxkeys,
350
                'marker' => $nextMarker,
351
            ];
352
353
            try {
354
                $listObjectInfo = $this->client->listObjects($this->bucket, $options);
355
            } catch (OssException $e) {
356
                $this->logErr(__FUNCTION__, $e);
357
                // return false;
358
                throw $e;
359
            }
360
361
            $nextMarker = $listObjectInfo->getNextMarker(); // 得到nextMarker,从上一次listObjects读到的最后一个文件的下一个文件开始继续获取文件列表
362
            $objectList = $listObjectInfo->getObjectList(); // 文件列表
363
            $prefixList = $listObjectInfo->getPrefixList(); // 目录列表
364
365
            if (!empty($objectList)) {
366
                foreach ($objectList as $objectInfo) {
367
                    $object = [];
368
                    $object['Prefix'] = $dirname;
369
                    $object['Key'] = $objectInfo->getKey();
370
                    $object['LastModified'] = $objectInfo->getLastModified();
371
                    $object['eTag'] = $objectInfo->getETag();
372
                    $object['Type'] = $objectInfo->getType();
373
                    $object['Size'] = $objectInfo->getSize();
374
                    $object['StorageClass'] = $objectInfo->getStorageClass();
375
376
                    $result['objects'][] = $object;
377
                }
378
            } else {
379
                $result["objects"] = [];
380
            }
381
382
            if (!empty($prefixList)) {
383
                foreach ($prefixList as $prefixInfo) {
384
                    $result['prefix'][] = $prefixInfo->getPrefix();
385
                }
386
            } else {
387
                $result['prefix'] = [];
388
            }
389
390
            //递归查询子目录所有文件
391
            if ($recursive) {
392
                foreach ($result['prefix'] as $pfix) {
393
                    $next = $this->listDirObjects($pfix, $recursive);
394
                    $result["objects"] = array_merge($result['objects'], $next["objects"]);
395
                }
396
            }
397
398
            //没有更多结果了
399
            if ($nextMarker === '') {
400
                break;
401
            }
402
        }
403
404
        return $result;
405
    }
406
407
    /**
408
     * {@inheritdoc}
409
     */
410
    public function has($path)
411
    {
412
        $object = $this->applyPathPrefix($path);
413
414
        return $this->client->doesObjectExist($this->bucket, $object);
415
    }
416
417
    /**
418
     * {@inheritdoc}
419
     */
420
    public function read($path)
421
    {
422
        $result = $this->readObject($path);
423
        $result['contents'] = (string)$result['raw_contents'];
424
        unset($result['raw_contents']);
425
        return $result;
426
    }
427
428
    /**
429
     * {@inheritdoc}
430
     */
431
    public function readStream($path)
432
    {
433
        $result = $this->readObject($path);
434
        $result['stream'] = $result['raw_contents'];
435
        rewind($result['stream']);
436
        // Ensure the EntityBody object destruction doesn't close the stream
437
        // $result['raw_contents']->detachStream();
438
        unset($result['raw_contents']);
439
440
        return $result;
441
    }
442
443
    /**
444
     * {@inheritdoc}
445
     */
446
    public function listContents($directory = '', $recursive = false)
447
    {
448
        $dirObjects = $this->listDirObjects($directory, true);
449
        $contents = $dirObjects["objects"];
450
451
        $result = array_map([$this, 'normalizeResponse'], $contents);
452
        $result = array_filter($result, function ($value) {
453
            return $value['path'] !== false;
454
        });
455
456
        return Util::emulateDirectories($result);
457
    }
458
459
    /**
460
     * {@inheritdoc}
461
     */
462 View Code Duplication
    public function getMetadata($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...
463
    {
464
        $object = $this->applyPathPrefix($path);
465
466
        try {
467
            $objectMeta = $this->client->getObjectMeta($this->bucket, $object);
468
        } catch (OssException $e) {
469
            $this->logErr(__FUNCTION__, $e);
470
            return false;
471
        }
472
473
        return $objectMeta;
474
    }
475
476
    /**
477
     * {@inheritdoc}
478
     */
479
    public function getSize($path)
480
    {
481
        $object = $this->getMetadata($path);
482
        $object['size'] = $object['content-length'];
483
        return $object;
484
    }
485
486
    /**
487
     * {@inheritdoc}
488
     */
489
    public function getMimetype($path)
490
    {
491
        if ($object = $this->getMetadata($path)) {
492
            $object['mimetype'] = $object['content-type'];
493
        }
494
        return $object;
495
    }
496
497
    /**
498
     * {@inheritdoc}
499
     */
500
    public function getTimestamp($path)
501
    {
502
        if ($object = $this->getMetadata($path)) {
503
            $object['timestamp'] = strtotime($object['last-modified']);
504
        }
505
        return $object;
506
    }
507
508
    /**
509
     * {@inheritdoc}
510
     */
511
    public function getVisibility($path)
512
    {
513
        $object = $this->applyPathPrefix($path);
514
        try {
515
            $acl = $this->client->getObjectAcl($this->bucket, $object);
516
        } catch (OssException $e) {
517
            $this->logErr(__FUNCTION__, $e);
518
            return false;
519
        }
520
521
        if ($acl == OssClient::OSS_ACL_TYPE_PUBLIC_READ) {
522
            $res['visibility'] = AdapterInterface::VISIBILITY_PUBLIC;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$res was never initialized. Although not strictly required by PHP, it is generally a good practice to add $res = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
523
        } else {
524
            $res['visibility'] = AdapterInterface::VISIBILITY_PRIVATE;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$res was never initialized. Although not strictly required by PHP, it is generally a good practice to add $res = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
525
        }
526
527
        return $res;
528
    }
529
530
    /**
531
     * @param string $path
532
     * @return array|null[]|string[]
533
     */
534
    protected function readObject($path)
535
    {
536
        $object = $this->applyPathPrefix($path);
537
        $result = [];
538
        $result['Body'] = $this->client->getObject($this->bucket, $object);
539
        $result = array_merge($result, ['type' => 'file']);
540
        return $this->normalizeResponse($result, $path);
541
    }
542
543
    /**
544
     * @param string $path
545
     * @return string
546
     */
547
    public function getUrl($path)
548
    {
549
        // if (!$this->has($path)) throw new FileNotFoundException($path.' not found');
550
        return ($this->ssl ? 'https://' : 'http://') . ($this->isCname ? ($this->cdnDomain == '' ? $this->endPoint : $this->cdnDomain) : $this->bucket . '.' . $this->endPoint) . '/' . ltrim($path, '/');
551
    }
552
553
    /**
554
     * Get a temporary URL for the file at the given path.
555
     *
556
     * @param string $path
557
     * @param \DateTimeInterface|int $expiration
558
     * @param array $options
559
     * @return string
560
     *
561
     * @throws \RuntimeException
562
     */
563
    public function getTemporaryUrl($path, $expiration, array $options = [])
564
    {
565
        if ($expiration instanceof Carbon) {
566
            return $this->client->generatePresignedUrl($this->bucket, $path, $expiration->getTimestamp(), $options);
0 ignored issues
show
Documentation introduced by
$options is of type array, but the function expects a string.

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...
567
        }
568
        return $this->client->signUrl($this->bucket, $path, $expiration, $options);
0 ignored issues
show
Bug introduced by
It seems like $expiration defined by parameter $expiration on line 563 can also be of type object<DateTimeInterface>; however, OSS\OssClient::signUrl() does only seem to accept integer, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
Documentation introduced by
$options is of type array, but the function expects a string.

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...
569
    }
570
571
    /**
572
     * The the ACL visibility.
573
     *
574
     * @param string $path
575
     *
576
     * @return string
577
     */
578
    protected function getObjectACL($path)
579
    {
580
        $metadata = $this->getVisibility($path);
581
582
        return $metadata['visibility'] === AdapterInterface::VISIBILITY_PUBLIC ? OssClient::OSS_ACL_TYPE_PUBLIC_READ : OssClient::OSS_ACL_TYPE_PRIVATE;
583
    }
584
585
    /**
586
     * Normalize a result from OSS.
587
     *
588
     * @param array $object
589
     * @param string $path
590
     *
591
     * @return array file metadata
592
     */
593 5
    protected function normalizeResponse(array $object, $path = null)
594
    {
595 5
        $result = ['path' => $path ?: $this->removePathPrefix(isset($object['Key']) ? $object['Key'] : $object['Prefix'])];
596 5
        $result['dirname'] = Util::dirname($result['path']);
597
598 5
        if (isset($object['LastModified'])) {
599
            $result['timestamp'] = strtotime($object['LastModified']);
600
        }
601
602 5
        if (substr($result['path'], -1) === '/') {
603
            $result['type'] = 'dir';
604
            $result['path'] = rtrim($result['path'], '/');
605
606
            return $result;
607
        }
608
609 5
        $result = array_merge($result, Util::map($object, static::$resultMap), ['type' => 'file']);
610
611 5
        return $result;
612
    }
613
614
    /**
615
     * Get options for a OSS call. done
616
     *
617
     * @param array $options
618
     *
619
     * @return array OSS options
620
     */
621 5
    protected function getOptions(array $options = [], Config $config = null)
622
    {
623 5
        $options = array_merge($this->options, $options);
624
625 5
        if ($config) {
626 5
            $options = array_merge($options, $this->getOptionsFromConfig($config));
627
        }
628
629 5
        return array(OssClient::OSS_HEADERS => $options);
630
    }
631
632
    /**
633
     * Retrieve options from a Config instance. done
634
     *
635
     * @param Config $config
636
     *
637
     * @return array
638
     */
639 5
    protected function getOptionsFromConfig(Config $config)
640
    {
641 5
        $options = [];
642
643 5
        foreach (static::$metaOptions as $option) {
644 5
            if (!$config->has($option)) {
645 5
                continue;
646
            }
647
            $options[static::$metaMap[$option]] = $config->get($option);
648
        }
649
650 5
        if ($visibility = $config->get('visibility')) {
651
            // Object ACL优先级高于Bucket ACL。
652 1
            $options[OssClient::OSS_OBJECT_ACL] = $visibility === AdapterInterface::VISIBILITY_PUBLIC ? OssClient::OSS_ACL_TYPE_PUBLIC_READ : OssClient::OSS_ACL_TYPE_PRIVATE;
653
        }
654
655 5
        if ($mimetype = $config->get('mimetype')) {
656
            $options[OssClient::OSS_CONTENT_TYPE] = $mimetype;
657
        }
658
659 5
        return $options;
660
    }
661
662
    /**
663
     * @param string $func
664
     * @param \Exception $e
665
     */
666
    protected function logErr($func, $e)
667
    {
668
        if ($this->debug) {
669
            Log::error($func . ": FAILED");
670
            Log::error($e->getMessage());
671
        }
672
    }
673
}
674