Passed
Pull Request — 6.0 (#2763)
by
unknown
12:42
created

Driver::size()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 0
cp 0
crap 2
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
    /**
109
     * Set the visibility for the given path.
110
     *
111
     * @param string $path
112
     * @param string $visibility
113
     * @return bool
114
     */
115 3
    public function setVisibility($path,$visibility)
116
    {
117 3
        try {
118 3
            $this->filesystem->setVisibility( $path,$visibility );
119
        } catch ( UnableToSetVisibility $e ) {
120 3
            throw_if( $this->throwsExceptions(),$e );
121
122 3
            return false;
123 3
        }
124
125
        return true;
126 3
    }
127
128
129 6
    /**
130
     * Delete the file at a given path.
131 6
     *
132
     * @param string|array $paths
133
     * @return bool
134
     */
135
    public function delete($paths)
136
    {
137
        $paths = is_array( $paths ) ? $paths : func_get_args();
138
139
        $success = true;
140
141
        foreach ( $paths as $path ) {
142
            try {
143
                $this->filesystem->delete( $path );
144
            } catch ( UnableToDeleteFile $e ) {
145
                throw_if( $this->throwsExceptions(),$e );
146
147
                $success = false;
148
            }
149
        }
150
151
        return $success;
152
    }
153
154
    /**
155
     * Copy a file to a new location.
156
     *
157
     * @param string $from
158
     * @param string $to
159
     * @return bool
160
     */
161
    public function copy($from,$to)
162
    {
163
        try {
164
            $this->filesystem->copy( $from,$to );
165
        } catch ( UnableToCopyFile $e ) {
166
            throw_if( $this->throwsExceptions(),$e );
167
168
            return false;
169
        }
170
171
        return true;
172
    }
173
174
    /**
175
     * Move a file to a new location.
176
     *
177
     * @param string $from
178
     * @param string $to
179
     * @return bool
180
     */
181
    public function move($from,$to)
182
    {
183
        try {
184
            $this->filesystem->move( $from,$to );
185
        } catch ( UnableToMoveFile $e ) {
186
            throw_if( $this->throwsExceptions(),$e );
187
188
            return false;
189
        }
190
191
        return true;
192
    }
193
194
    /**
195
     * Get the file size of a given file.
196
     *
197
     * @param string $path
198
     * @return int
199
     * @throws FilesystemException
200
     */
201
    public function size($path)
202
    {
203
        return $this->filesystem->fileSize( $path );
204
    }
205
206
    /**
207
     * Get the mime-type of a given file.
208
     *
209
     * @param string $path
210
     * @return string|false
211
     */
212
    public function mimeType($path)
213
    {
214
        try {
215
            return $this->filesystem->mimeType( $path );
216
        } catch ( UnableToRetrieveMetadata $e ) {
217
            throw_if( $this->throwsExceptions(),$e );
218
        }
219
220
        return false;
221
    }
222
223
    /**
224
     * Get the file's last modification time.
225
     *
226
     * @param string $path
227
     * @return int
228
     */
229
    public function lastModified($path): int
230
    {
231
        return $this->filesystem->lastModified( $path );
232
    }
233
234
235
    /**
236
     * {@inheritdoc}
237
     */
238
    public function readStream($path)
239
    {
240
        try {
241
            return $this->filesystem->readStream( $path );
242
        } catch ( UnableToReadFile $e ) {
243
            throw_if( $this->throwsExceptions(),$e );
244
        }
245
    }
246
247
    /**
248
     * {@inheritdoc}
249
     */
250
    public function writeStream($path,$resource,array $options = [])
251
    {
252
        try {
253
            $this->filesystem->writeStream( $path,$resource,$options );
254
        } catch ( UnableToWriteFile|UnableToSetVisibility $e ) {
255
            throw_if( $this->throwsExceptions(),$e );
256
257
            return false;
258
        }
259
260
        return true;
261
    }
262
263
    protected function getLocalUrl($path)
264
    {
265
        if (isset( $this->config['url'] )) {
266
            return $this->concatPathToUrl( $this->config['url'],$path );
267
        }
268
269
        return $path;
270
    }
271
272
    protected function concatPathToUrl($url,$path)
273
    {
274
        return rtrim( $url,'/' ).'/'.ltrim( $path,'/' );
275
    }
276
277
    public function url(string $path): string
278
    {
279
        $adapter = $this->adapter;
280
281
        if (method_exists( $adapter,'getUrl' )) {
282
            return $adapter->getUrl( $path );
283
        } elseif (method_exists( $this->filesystem,'getUrl' )) {
284
            return $this->filesystem->getUrl( $path );
285
        } elseif ($adapter instanceof LocalFilesystemAdapter) {
286
            return $this->getLocalUrl( $path );
287
        } else {
288
            throw new RuntimeException( 'This driver does not support retrieving URLs.' );
289
        }
290
    }
291
292
    /**
293
     * Get the Flysystem adapter.
294
     *
295
     * @return \League\Flysystem\FilesystemAdapter
296
     */
297
    public function getAdapter()
298
    {
299
        return $this->adapter;
300
    }
301
302
    /**
303
     * 保存文件
304
     * @param string $path 路径
305
     * @param File|string $file 文件
306
     * @param null|string|\Closure $rule 文件名规则
307
     * @param array $options 参数
308
     * @return bool|string
309
     */
310
    public function putFile(string $path,$file,$rule = null,array $options = [])
311
    {
312
        $file = is_string( $file ) ? new File( $file ) : $file;
313
        return $this->putFileAs( $path,$file,$file->hashName( $rule ),$options );
314
    }
315
316
    /**
317
     * 指定文件名保存文件
318
     * @param string $path 路径
319
     * @param File $file 文件
320
     * @param string $name 文件名
321
     * @param array $options 参数
322
     * @return bool|string
323
     */
324
    public function putFileAs(string $path,File $file,string $name,array $options = [])
325
    {
326
        $stream = fopen( $file->getRealPath(),'r' );
327
        $path   = trim( $path.'/'.$name,'/' );
328
329
        $result = $this->put( $path,$stream,$options );
330
331
        if (is_resource( $stream )) {
332
            fclose( $stream );
333
        }
334
335
        return $result ? $path : false;
336
    }
337
338
    public function put($path,$contents,$options = [])
339
    {
340
        $options = is_string( $options )
341
            ? ['visibility' => $options]
342
            : (array)$options;
343
344
        // If the given contents is actually a file or uploaded file instance than we will
345
        // automatically store the file using a stream. This provides a convenient path
346
        // for the developer to store streams without managing them manually in code.
347
        if ($contents instanceof File ||
348
            $contents instanceof UploadedFile) {
349
            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

349
            return $this->putFile( $path,$contents,/** @scrutinizer ignore-type */ $options );
Loading history...
350
        }
351
352
        try {
353
            if ($contents instanceof StreamInterface) {
354
                $this->writeStream( $path,$contents->detach(),$options );
355
356
                return true;
357
            }
358
359
            is_resource( $contents )
360
                ? $this->writeStream( $path,$contents,$options )
361
                : $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

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