Passed
Pull Request — 6.0 (#2763)
by
unknown
11:24
created

Driver::getLocalUrl()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 7
ccs 0
cts 0
cp 0
crap 6
rs 10
c 0
b 0
f 0
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <[email protected]>
10
// +----------------------------------------------------------------------
11
declare ( strict_types = 1 );
12
13
namespace think\filesystem;
14
15
use League\Flysystem\Filesystem;
16
use League\Flysystem\FilesystemAdapter;
17
use League\Flysystem\FilesystemException;
18
use League\Flysystem\Local\LocalFilesystemAdapter;
19
use League\Flysystem\PathPrefixer;
20
use League\Flysystem\StorageAttributes;
21
use League\Flysystem\UnableToCopyFile;
22
use League\Flysystem\UnableToCreateDirectory;
23
use League\Flysystem\UnableToDeleteDirectory;
24
use League\Flysystem\UnableToDeleteFile;
25
use League\Flysystem\UnableToMoveFile;
26
use League\Flysystem\UnableToReadFile;
27
use League\Flysystem\UnableToRetrieveMetadata;
28
use League\Flysystem\UnableToSetVisibility;
29
use League\Flysystem\UnableToWriteFile;
30
use Psr\Http\Message\StreamInterface;
31
use RuntimeException;
32
use think\File;
33
use think\file\UploadedFile;
34
use think\helper\Arr;
35
36
/**
37
 * Class Driver
38
 * @package think\filesystem
39
 * @mixin Filesystem
40
 */
41
abstract class Driver
42
{
43 9
44
    /** @var Filesystem */
45 9
    protected $filesystem;
46 9
47
    protected $adapter;
48 9
49 9
    /**
50 9
     * The Flysystem PathPrefixer instance.
51
     *
52 6
     * @var PathPrefixer
53
     */
54 6
    protected $prefixer;
55 6
56
    /**
57
     * 配置参数
58 3
     * @var array
59 3
     */
60 3
    protected $config = [];
61 3
62
    public function __construct(array $config)
63
    {
64
        $this->config   = array_merge( $this->config,$config );
65
        $separator      = $config['directory_separator'] ?? DIRECTORY_SEPARATOR;
66
        $this->prefixer = new PathPrefixer( $config['root'] ?? '',$separator );
67 9
68
        if (isset( $config['prefix'] )) {
69 9
            $this->prefixer = new PathPrefixer( $this->prefixer->prefixPath( $config['prefix'] ),$separator );
70 6
        }
71
72
73 9
        $this->adapter    = $this->createAdapter();
74
        $this->filesystem = $this->createFilesystem( $this->adapter,$this->config );
75 9
    }
76
77
78
    abstract protected function createAdapter();
79
80
    /**
81
     * @param FilesystemAdapter $adapter
82
     * @param array $config
83
     * @return Filesystem
84
     */
85
    protected function createFilesystem(FilesystemAdapter $adapter,array $config)
86
    {
87
        return new Filesystem( $adapter,Arr::only( $config,[
88
            'directory_visibility',
89
            'disable_asserts',
90
            'temporary_url',
91
            'url',
92
            'visibility',
93
        ] ) );
94
    }
95
96
97
    /**
98
     * 获取文件完整路径
99
     * @param string $path
100
     * @return string
101
     */
102 3
    public function path(string $path): string
103
    {
104 3
        return $this->prefixer->prefixPath( $path );
105
    }
106
107
    /**
108
     * Determine if a file or directory exists.
109
     *
110
     * @param string $path
111
     * @return bool
112
     */
113
    public function exists($path)
114
    {
115 3
        return $this->adapter->fileExists( $path ) || $this->adapter->directoryExists( $path );
116
    }
117 3
118 3
    /**
119
     * Determine if a file or directory is missing.
120 3
     *
121
     * @param string $path
122 3
     * @return bool
123 3
     */
124
    public function missing($path)
125
    {
126 3
        return !$this->exists( $path );
127
    }
128
129 6
130
    /**
131 6
     * Set the visibility for the given path.
132
     *
133
     * @param string $path
134
     * @param string $visibility
135
     * @return bool
136
     */
137
    public function setVisibility($path,$visibility)
138
    {
139
        try {
140
            $this->filesystem->setVisibility( $path,$visibility );
141
        } catch ( UnableToSetVisibility $e ) {
142
            throw_if( $this->throwsExceptions(),$e );
143
144
            return false;
145
        }
146
147
        return true;
148
    }
149
150
151
    /**
152
     * Delete the file at a given path.
153
     *
154
     * @param string|array $paths
155
     * @return bool
156
     */
157
    public function delete($paths)
158
    {
159
        $paths = is_array( $paths ) ? $paths : func_get_args();
160
161
        $success = true;
162
163
        foreach ( $paths as $path ) {
164
            try {
165
                $this->filesystem->delete( $path );
166
            } catch ( UnableToDeleteFile $e ) {
167
                throw_if( $this->throwsExceptions(),$e );
168
169
                $success = false;
170
            }
171
        }
172
173
        return $success;
174
    }
175
176
    /**
177
     * Copy a file to a new location.
178
     *
179
     * @param string $from
180
     * @param string $to
181
     * @return bool
182
     */
183
    public function copy($from,$to)
184
    {
185
        try {
186
            $this->filesystem->copy( $from,$to );
187
        } catch ( UnableToCopyFile $e ) {
188
            throw_if( $this->throwsExceptions(),$e );
189
190
            return false;
191
        }
192
193
        return true;
194
    }
195
196
    /**
197
     * Move a file to a new location.
198
     *
199
     * @param string $from
200
     * @param string $to
201
     * @return bool
202
     */
203
    public function move($from,$to)
204
    {
205
        try {
206
            $this->filesystem->move( $from,$to );
207
        } catch ( UnableToMoveFile $e ) {
208
            throw_if( $this->throwsExceptions(),$e );
209
210
            return false;
211
        }
212
213
        return true;
214
    }
215
216
    /**
217
     * Get the file size of a given file.
218
     *
219
     * @param string $path
220
     * @return int
221
     * @throws FilesystemException
222
     */
223
    public function size($path)
224
    {
225
        return $this->filesystem->fileSize( $path );
226
    }
227
228
    /**
229
     * Get the mime-type of a given file.
230
     *
231
     * @param string $path
232
     * @return string|false
233
     */
234
    public function mimeType($path)
235
    {
236
        try {
237
            return $this->filesystem->mimeType( $path );
238
        } catch ( UnableToRetrieveMetadata $e ) {
239
            throw_if( $this->throwsExceptions(),$e );
240
        }
241
242
        return false;
243
    }
244
245
    /**
246
     * Get the file's last modification time.
247
     *
248
     * @param string $path
249
     * @return int
250
     */
251
    public function lastModified($path): int
252
    {
253
        return $this->filesystem->lastModified( $path );
254
    }
255
256
257
    /**
258
     * {@inheritdoc}
259
     */
260
    public function readStream($path)
261
    {
262
        try {
263
            return $this->filesystem->readStream( $path );
264
        } catch ( UnableToReadFile $e ) {
265
            throw_if( $this->throwsExceptions(),$e );
266
        }
267
    }
268
269
    /**
270
     * {@inheritdoc}
271
     */
272
    public function writeStream($path,$resource,array $options = [])
273
    {
274
        try {
275
            $this->filesystem->writeStream( $path,$resource,$options );
276
        } catch ( UnableToWriteFile|UnableToSetVisibility $e ) {
277
            throw_if( $this->throwsExceptions(),$e );
278
279
            return false;
280
        }
281
282
        return true;
283
    }
284
285
    protected function getLocalUrl($path)
286
    {
287
        if (isset( $this->config['url'] )) {
288
            return $this->concatPathToUrl( $this->config['url'],$path );
289
        }
290
291
        return $path;
292
    }
293
294
    protected function concatPathToUrl($url,$path)
295
    {
296
        return rtrim( $url,'/' ).'/'.ltrim( $path,'/' );
297
    }
298
299
    public function url(string $path): string
300
    {
301
        $adapter = $this->adapter;
302
303
        if (method_exists( $adapter,'getUrl' )) {
304
            return $adapter->getUrl( $path );
305
        } elseif (method_exists( $this->filesystem,'getUrl' )) {
306
            return $this->filesystem->getUrl( $path );
307
        } elseif ($adapter instanceof LocalFilesystemAdapter) {
308
            return $this->getLocalUrl( $path );
309
        } else {
310
            throw new RuntimeException( 'This driver does not support retrieving URLs.' );
311
        }
312
    }
313
314
    /**
315
     * Get the Flysystem adapter.
316
     *
317
     * @return \League\Flysystem\FilesystemAdapter
318
     */
319
    public function getAdapter()
320
    {
321
        return $this->adapter;
322
    }
323
324
    /**
325
     * 保存文件
326
     * @param string $path 路径
327
     * @param File|string $file 文件
328
     * @param null|string|\Closure $rule 文件名规则
329
     * @param array $options 参数
330
     * @return bool|string
331
     */
332
    public function putFile(string $path,$file,$rule = null,array $options = [])
333
    {
334
        $file = is_string( $file ) ? new File( $file ) : $file;
335
        return $this->putFileAs( $path,$file,$file->hashName( $rule ),$options );
336
    }
337
338
    /**
339
     * 指定文件名保存文件
340
     * @param string $path 路径
341
     * @param File $file 文件
342
     * @param string $name 文件名
343
     * @param array $options 参数
344
     * @return bool|string
345
     */
346
    public function putFileAs(string $path,File $file,string $name,array $options = [])
347
    {
348
        $stream = fopen( $file->getRealPath(),'r' );
349
        $path   = trim( $path.'/'.$name,'/' );
350
351
        $result = $this->put( $path,$stream,$options );
352
353
        if (is_resource( $stream )) {
354
            fclose( $stream );
355
        }
356
357
        return $result ? $path : false;
358
    }
359
360
    public function put($path,$contents,$options = [])
361
    {
362
        $options = is_string( $options )
363
            ? ['visibility' => $options]
364
            : (array)$options;
365
366
        // If the given contents is actually a file or uploaded file instance than we will
367
        // automatically store the file using a stream. This provides a convenient path
368
        // for the developer to store streams without managing them manually in code.
369
        if ($contents instanceof File ||
370
            $contents instanceof UploadedFile) {
371
            return $this->putFile( $path,$contents,$options );
0 ignored issues
show
Bug introduced by
$options of type array|array<string,string> is incompatible with the type Closure|null|string expected by parameter $rule of think\filesystem\Driver::putFile(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

371
            return $this->putFile( $path,$contents,/** @scrutinizer ignore-type */ $options );
Loading history...
372
        }
373
374
        try {
375
            if ($contents instanceof StreamInterface) {
376
                $this->writeStream( $path,$contents->detach(),$options );
377
378
                return true;
379
            }
380
381
            is_resource( $contents )
382
                ? $this->writeStream( $path,$contents,$options )
383
                : $this->write( $path,$contents,$options );
0 ignored issues
show
Bug introduced by
The method write() does not exist on think\filesystem\Driver. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

383
                : $this->/** @scrutinizer ignore-call */ write( $path,$contents,$options );
Loading history...
384
        } catch ( UnableToWriteFile|UnableToSetVisibility $e ) {
385
            throw_if( $this->throwsExceptions(),$e );
386
387
            return false;
388
        }
389
390
        return true;
391
    }
392
393
    /**
394
     * Get an array of all files in a directory.
395
     *
396
     * @param string|null $directory
397
     * @param bool $recursive
398
     * @return array
399
     */
400
    public function files($directory = null,$recursive = false)
401
    {
402
        return $this->filesystem->listContents( $directory ?? '',$recursive )
403
            ->filter( function (StorageAttributes $attributes) {
404
                return $attributes->isFile();
405
            } )
406
            ->sortByPath()
407
            ->map( function (StorageAttributes $attributes) {
408
                return $attributes->path();
409
            } )
410
            ->toArray();
411
    }
412
413
    /**
414
     * Get all of the files from the given directory (recursive).
415
     *
416
     * @param string|null $directory
417
     * @return array
418
     */
419
    public function allFiles($directory = null)
420
    {
421
        return $this->files( $directory,true );
422
    }
423
424
    /**
425
     * Get all of the directories within a given directory.
426
     *
427
     * @param string|null $directory
428
     * @param bool $recursive
429
     * @return array
430
     */
431
    public function directories($directory = null,$recursive = false)
432
    {
433
        return $this->filesystem->listContents( $directory ?? '',$recursive )
434
            ->filter( function (StorageAttributes $attributes) {
435
                return $attributes->isDir();
436
            } )
437
            ->map( function (StorageAttributes $attributes) {
438
                return $attributes->path();
439
            } )
440
            ->toArray();
441
    }
442
443
    /**
444
     * Get all the directories within a given directory (recursive).
445
     *
446
     * @param string|null $directory
447
     * @return array
448
     */
449
    public function allDirectories($directory = null)
450
    {
451
        return $this->directories( $directory,true );
452
    }
453
454
    /**
455
     * Create a directory.
456
     *
457
     * @param string $path
458
     * @return bool
459
     */
460
    public function makeDirectory($path)
461
    {
462
        try {
463
            $this->filesystem->createDirectory( $path );
464
        } catch ( UnableToCreateDirectory|UnableToSetVisibility $e ) {
465
            throw_if( $this->throwsExceptions(),$e );
466
467
            return false;
468
        }
469
470
        return true;
471
    }
472
473
    /**
474
     * Recursively delete a directory.
475
     *
476
     * @param string $directory
477
     * @return bool
478
     */
479
    public function deleteDirectory($directory)
480
    {
481
        try {
482
            $this->filesystem->deleteDirectory( $directory );
483
        } catch ( UnableToDeleteDirectory $e ) {
484
            throw_if( $this->throwsExceptions(),$e );
485
486
            return false;
487
        }
488
489
        return true;
490
    }
491
492
    /**
493
     * Determine if Flysystem exceptions should be thrown.
494
     *
495
     * @return bool
496
     */
497
    protected function throwsExceptions(): bool
498
    {
499
        return (bool)( $this->config['throw'] ?? false );
500
    }
501
502
    public function __call($method,$parameters)
503
    {
504
        return $this->filesystem->$method( ...$parameters );
505
    }
506
}
507