Passed
Push — master ( 1c9fad...08ce17 )
by Thomas
02:32
created

BaiduBosAdapter::getAcl()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 6
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 11
rs 10
1
<?php
2
3
namespace Sulao\Flysystem\BaiduBos;
4
5
use Exception;
6
use League\Flysystem\Adapter\AbstractAdapter;
7
use League\Flysystem\Config;
8
use League\Flysystem\Util;
9
use Sulao\BaiduBos\Client;
10
11
class BaiduBosAdapter extends AbstractAdapter
12
{
13
    /**
14
     * @var Client
15
     */
16
    protected $client;
17
18
    /**
19
     * BaiduBosAdapter constructor.
20
     *
21
     * @param Client $client
22
     */
23
    public function __construct(Client $client)
24
    {
25
        $this->client = $client;
26
    }
27
28
    /**
29
     * @return Client
30
     */
31
    public function getClient()
32
    {
33
        return $this->client;
34
    }
35
36
    /**
37
     * Write a new file.
38
     *
39
     * @param string $path
40
     * @param string $contents
41
     * @param Config $config   Config object
42
     *
43
     * @return array|false false on failure file meta data on success
44
     */
45
    public function write($path, $contents, Config $config)
46
    {
47
        try {
48
            $this->client
49
                ->putObject($path, $contents, $this->extractOptions($config));
50
        } catch (Exception $exception) {
51
            return  false;
52
        }
53
54
        return $this->client->getObjectMeta($path);
55
    }
56
57
    /**
58
     * Write a new file using a stream.
59
     *
60
     * @param string   $path
61
     * @param resource $resource
62
     * @param Config   $config   Config object
63
     *
64
     * @return array|false false on failure file meta data on success
65
     */
66
    public function writeStream($path, $resource, Config $config)
67
    {
68
        return $this->write($path, stream_get_contents($resource), $config);
69
    }
70
71
    /**
72
     * Update a file.
73
     *
74
     * @param string $path
75
     * @param string $contents
76
     * @param Config $config   Config object
77
     *
78
     * @return array|false false on failure file meta data on success
79
     */
80
    public function update($path, $contents, Config $config)
81
    {
82
        return $this->write($path, $contents, $config);
83
    }
84
85
    /**
86
     * Update a file using a stream.
87
     *
88
     * @param string   $path
89
     * @param resource $resource
90
     * @param Config   $config   Config object
91
     *
92
     * @return array|false false on failure file meta data on success
93
     */
94
    public function updateStream($path, $resource, Config $config)
95
    {
96
        return $this->writeStream($path, $resource, $config);
97
    }
98
99
    /**
100
     * Rename a file.
101
     *
102
     * @param string $path
103
     * @param string $newPath
104
     *
105
     * @return bool
106
     */
107
    public function rename($path, $newPath)
108
    {
109
        try {
110
            $this->client->copyObject($path, $newPath);
111
            $this->client->deleteObject($path);
112
        } catch (Exception $exception) {
113
            return false;
114
        }
115
116
        return true;
117
    }
118
119
    /**
120
     * Copy a file.
121
     *
122
     * @param string $path
123
     * @param string $newPath
124
     *
125
     * @return bool
126
     */
127
    public function copy($path, $newPath)
128
    {
129
        try {
130
            $this->client->copyObject($path, $newPath);
131
        } catch (Exception $exception) {
132
            return false;
133
        }
134
135
        return true;
136
    }
137
138
    /**
139
     * Delete a file.
140
     *
141
     * @param string $path
142
     *
143
     * @return bool
144
     */
145
    public function delete($path)
146
    {
147
        try {
148
            $this->client->deleteObject($path);
149
        } catch (Exception $exception) {
150
            return false;
151
        }
152
153
        return true;
154
    }
155
156
    /**
157
     * Delete a directory.
158
     *
159
     * @param string $dirname
160
     *
161
     * @return bool
162
     */
163
    public function deleteDir($dirname)
164
    {
165
        try {
166
            $this->client->deleteObject(rtrim($dirname, '/') . '/');
167
        } catch (Exception $exception) {
168
            return false;
169
        }
170
171
        return true;
172
    }
173
174
    /**
175
     * Create a directory.
176
     *
177
     * @param string $dirname directory name
178
     * @param Config $config
179
     *
180
     * @return bool
181
     */
182
    public function createDir($dirname, Config $config)
183
    {
184
        try {
185
            $this->client->putObject(
186
                rtrim($dirname, '/') . '/',
187
                '',
188
                $this->extractOptions($config)
189
            );
190
        } catch (Exception $exception) {
191
            return false;
192
        }
193
194
        return true;
0 ignored issues
show
Bug Best Practice introduced by
The expression return true returns the type true which is incompatible with the return type mandated by League\Flysystem\AdapterInterface::createDir() of array|false.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
195
    }
196
197
    /**
198
     * Check whether a file exists.
199
     *
200
     * @param string $path
201
     *
202
     * @return bool
203
     */
204
    public function has($path)
205
    {
206
        try {
207
            $this->client->getObjectMeta($path);
208
        } catch (Exception $exception) {
209
            return false;
210
        }
211
212
        return true;
213
    }
214
215
    /**
216
     * Read a file.
217
     *
218
     * @param string $path
219
     *
220
     * @return array|false
221
     */
222
    public function read($path)
223
    {
224
        try {
225
            $contents = $this->client->getObject($path);
226
        } catch (Exception $exception) {
227
            return false;
228
        }
229
230
        return compact('path', 'contents');
231
    }
232
233
    /**
234
     * Read a file as a stream.
235
     *
236
     * @param string $path
237
     *
238
     * @return array|false
239
     */
240
    public function readStream($path)
241
    {
242
        $result = $this->read($path);
243
        if ($result === false) {
244
            return false;
245
        }
246
247
        $stream = fopen('php://temp', 'w+b');
248
        fputs($stream, $result['contents']);
249
        rewind($stream);
250
251
        return compact('path', 'stream');
252
    }
253
254
    /**
255
     * List contents of a directory.
256
     *
257
     * @param string $directory
258
     * @param bool   $recursive
259
     *
260
     * @return array
261
     */
262
    public function listContents($directory = '', $recursive = false)
263
    {
264
        $options = [];
265
266
        if (!$recursive) {
267
            $options['query']['delimiter'] = '/';
268
        }
269
270
        $directory = trim($directory, '/');
271
        if ($directory !== '') {
272
            $directory .= '/';
273
            $options['query']['prefix'] = $directory;
274
        }
275
276
        $result = $this->client->listObjects($options);
277
278
        $contents = [];
279
        foreach ($result['contents'] as $row) {
280
            if ($row['key'] === $directory) {
281
                continue;
282
            }
283
284
            $contents[] = $this->normalizeContent($row);
285
        }
286
287
        return $contents;
288
    }
289
290
    /**
291
     * Get all the meta data of a file or directory.
292
     *
293
     * @param string $path
294
     *
295
     * @return array|false
296
     */
297
    public function getMetadata($path)
298
    {
299
        try {
300
            $meta = $this->client->getObjectMeta($path);
301
        } catch (Exception $exception) {
302
            return false;
303
        }
304
305
        return $this->normalizeMeta($meta, $path);
306
    }
307
308
    /**
309
     * Get the size of a file.
310
     *
311
     * @param string $path
312
     *
313
     * @return array|false
314
     */
315
    public function getSize($path)
316
    {
317
        return $this->getMetadata($path);
318
    }
319
320
    /**
321
     * Get the mime-type of a file.
322
     *
323
     * @param string $path
324
     *
325
     * @return array|false
326
     */
327
    public function getMimeType($path)
328
    {
329
        return $this->getMetadata($path);
330
    }
331
332
    /**
333
     * Get the timestamp of a file.
334
     *
335
     * @param string $path
336
     *
337
     * @return array|false
338
     */
339
    public function getTimestamp($path)
340
    {
341
        return $this->getMetadata($path);
342
    }
343
344
    /**
345
     * Get the visibility of a file.
346
     *
347
     * @param string $path
348
     *
349
     * @return array|false
350
     */
351
    public function getVisibility($path)
352
    {
353
        $acl = $this->getObjectAcl($path);
354
        if ($acl === false) {
355
            return false;
356
        }
357
358
        $permissions = $this->extractPermissions($acl);
359
360
        if (in_array('READ', $permissions)) {
361
            $visibility = 'public-read';
362
        } else {
363
            $visibility = 'private';
364
        }
365
366
        return compact('path', 'visibility');
367
    }
368
369
    /**
370
     * Set the visibility for a file.
371
     *
372
     * @param string $path
373
     * @param string $visibility
374
     *
375
     * @return array|false file meta data
376
     */
377
    public function setVisibility($path, $visibility)
378
    {
379
        try {
380
            $this->client->putObjectAcl($path, $visibility);
381
        } catch (Exception $exception) {
382
            return false;
383
        }
384
385
        return compact('path', 'visibility');
386
    }
387
388
    /**
389
     * Extract options from config
390
     *
391
     * @param Config $config
392
     *
393
     * @return array
394
     */
395
    protected function extractOptions(Config $config)
396
    {
397
        $options = [];
398
399
        foreach (['headers', 'query', 'body', 'request', 'authorize'] as $key) {
400
            if ($config->has($key)) {
401
                $options[$key] = $config->get($key);
402
            }
403
        }
404
405
        return $options;
406
    }
407
408
    /**
409
     * Normalize the object meta array.
410
     *
411
     * @param array $meta
412
     * @param string $path
413
     *
414
     * @return array
415
     */
416
    protected function normalizeMeta(array $meta, $path)
417
    {
418
        $result =  Util::pathinfo($path);
419
420
        if (isset($meta['Last-Modified'])) {
421
            $result['timestamp'] = strtotime($meta['Last-Modified']);
422
        }
423
424
        return array_merge($result, Util::map($meta, [
425
            'Content-Length' => 'size',
426
            'Content-Type'   => 'mimetype',
427
        ]), ['type' => 'file']);
428
    }
429
430
    /**
431
     * Normalize the content from list contents of dir.
432
     *
433
     * @param array $content
434
     *
435
     * @return array
436
     */
437
    protected function normalizeContent(array $content)
438
    {
439
        $return = [];
440
441
        if (substr($content['key'], -1) === '/') {
442
            $return['type'] = 'dir';
443
            $return['path'] = rtrim($content['key'], '/');
444
        } else {
445
            $return['type'] = 'file';
446
            $return['path'] = $content['key'];
447
            $return['size'] = $content['size'];
448
        }
449
450
        $return['timestamp'] = strtotime($content['lastModified']);
451
452
        return $return + Util::pathinfo($content['key']);
453
    }
454
455
    /**
456
     * Get object acl, if not set, return bucket acl
457
     *
458
     * @param $path
459
     *
460
     * @return array|false
461
     */
462
    protected function getObjectAcl($path)
463
    {
464
        try {
465
            $result = $this->client->getObjectAcl($path);
466
            return $result['accessControlList'];
467
        } catch (Exception $exception) {
468
            if ($exception->getCode() == 404) {
469
                return $this->getBucketAcl();
470
            }
471
        }
472
473
        return false;
474
    }
475
476
    /**
477
     * Get bucket acl
478
     *
479
     * @return array|false
480
     */
481
    protected function getBucketAcl()
482
    {
483
        try {
484
            $result = $this->client->getBucketAcl();
485
        } catch (Exception $exception) {
486
            return false;
487
        }
488
489
        return $result['accessControlList'];
490
    }
491
492
    /**
493
     * Extract permissions from acl
494
     *
495
     * @param array $acl
496
     *
497
     * @return array
498
     */
499
    protected function extractPermissions(array $acl)
500
    {
501
        $permissions = [];
502
        foreach ($acl as $row) {
503
            $ids = array_column($row['grantee'], 'id');
504
            if (in_array('*', $ids)) {
505
                $permissions = $row['permission'];
506
                break;
507
            }
508
        }
509
510
        return $permissions;
511
    }
512
}
513