Completed
Push — master ( 675097...51fab9 )
by duan
01:47
created

Filesystem::copyDirectory()   B

Complexity

Conditions 8
Paths 11

Size

Total Lines 31
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 8.4218

Importance

Changes 0
Metric Value
cc 8
eloc 16
nc 11
nop 3
dl 0
loc 31
ccs 13
cts 16
cp 0.8125
crap 8.4218
rs 8.4444
c 0
b 0
f 0
1
<?php
2
3
namespace Yiranzai\File;
4
5
use FilesystemIterator;
6
7
class Filesystem
8
{
9
10
    /**
11
     * Determine if a file or directory exists.
12
     *
13
     * @param  string $path
14
     * @return bool
15
     */
16 12
    public function exists($path): bool
17
    {
18 12
        return file_exists($path);
19
    }
20
21
    /**
22
     * Get the contents of a file.
23
     *
24
     * @param  string $path
25
     * @param  bool   $lock
26
     * @return string
27
     */
28 9
    public function get($path, $lock = false): string
29
    {
30 9
        if ($this->isFile($path)) {
31 6
            return $lock ? $this->sharedGet($path) : file_get_contents($path);
32
        }
33
34 3
        throw new \RuntimeException("File does not exist at path {$path}");
35
    }
36
37
    /**
38
     * Get contents of a file with shared access.
39
     *
40
     * @param  string $path
41
     * @return string
42
     */
43 3
    public function sharedGet($path): string
44
    {
45 3
        $contents = '';
46
47 3
        $handle = fopen($path, 'rb');
48
49 3
        if ($handle !== false) {
50
            try {
51 3
                if (flock($handle, LOCK_SH)) {
52 3
                    clearstatcache(true, $path);
53
54 3
                    $contents = fread($handle, $this->size($path) ?: 1);
55
56 3
                    flock($handle, LOCK_UN);
57
                }
58 3
            } finally {
59 3
                fclose($handle);
60
            }
61
        }
62
63 3
        return $contents;
64
    }
65
66
    /**
67
     * Get the MD5 hash of the file at the given path.
68
     *
69
     * @param  string $path
70
     * @return string
71
     */
72 3
    public function hash($path): string
73
    {
74 3
        return md5_file($path);
75
    }
76
77
    /**
78
     * Write the contents of a file.
79
     *
80
     * @param  string $path
81
     * @param  string $contents
82
     * @param  bool   $lock
83
     * @return int
84
     */
85 6
    public function put($path, $contents, $lock = false): int
86
    {
87 6
        return file_put_contents($path, $contents, $lock ? LOCK_EX : 0);
88
    }
89
90
    /**
91
     * Prepend to a file.
92
     *
93
     * @param  string $path
94
     * @param  string $data
95
     * @return int
96
     */
97 3
    public function prepend($path, $data): int
98
    {
99 3
        if ($this->exists($path)) {
100 3
            return $this->put($path, $data . $this->get($path));
101
        }
102
103 3
        return $this->put($path, $data);
104
    }
105
106
    /**
107
     * Append to a file.
108
     *
109
     * @param  string $path
110
     * @param  string $data
111
     * @return int
112
     */
113 3
    public function append($path, $data): int
114
    {
115 3
        return file_put_contents($path, $data, FILE_APPEND);
116
    }
117
118
    /**
119
     * Get or set UNIX mode of a file or directory.
120
     *
121
     * @param  string $path
122
     * @param  int    $mode
123
     * @return mixed
124
     */
125 9
    public function chmod($path, $mode = null)
126
    {
127 9
        if ($mode !== null) {
128 9
            return chmod($path, $mode);
129
        }
130
131 3
        return substr(sprintf('%o', fileperms($path)), -4);
132
    }
133
134
    /**
135
     * Delete the file at a given path.
136
     *
137
     * @param  string|array $paths
138
     * @return bool
139
     */
140 6
    public function delete($paths): bool
141
    {
142 6
        $paths = is_array($paths) ? $paths : func_get_args();
143
144 6
        $success = true;
145
146 6
        foreach ($paths as $path) {
147
            try {
148 6
                if (!@unlink($path)) {
149 6
                    $success = false;
150
                }
151
            } catch (\Exception $e) {
152 4
                $success = false;
153
            }
154
        }
155
156 6
        return $success;
157
    }
158
159
    /**
160
     * Move a file to a new location.
161
     *
162
     * @param  string $path
163
     * @param  string $target
164
     * @return bool
165
     */
166 3
    public function move($path, $target): bool
167
    {
168 3
        return rename($path, $target);
169
    }
170
171
    /**
172
     * Copy a file to a new location.
173
     *
174
     * @param  string $path
175
     * @param  string $target
176
     * @return bool
177
     */
178 3
    public function copy($path, $target): bool
179
    {
180 3
        return copy($path, $target);
181
    }
182
183
    /**
184
     * Extract the file name from a file path.
185
     *
186
     * @param  string $path
187
     * @return string
188
     */
189 3
    public function name($path): string
190
    {
191 3
        return pathinfo($path, PATHINFO_FILENAME);
192
    }
193
194
    /**
195
     * Extract the trailing name component from a file path.
196
     *
197
     * @param  string $path
198
     * @return string
199
     */
200 3
    public function basename($path): string
201
    {
202 3
        return pathinfo($path, PATHINFO_BASENAME);
203
    }
204
205
    /**
206
     * Extract the parent directory from a file path.
207
     *
208
     * @param  string $path
209
     * @return string
210
     */
211 3
    public function dirname($path): string
212
    {
213 3
        return pathinfo($path, PATHINFO_DIRNAME);
214
    }
215
216
    /**
217
     * Extract the file extension from a file path.
218
     *
219
     * @param  string $path
220
     * @return string
221
     */
222 3
    public function extension($path): string
223
    {
224 3
        return pathinfo($path, PATHINFO_EXTENSION);
225
    }
226
227
    /**
228
     * Get the file type of a given file.
229
     *
230
     * @param  string $path
231
     * @return string
232
     */
233 3
    public function type($path): string
234
    {
235 3
        return filetype($path);
236
    }
237
238
    /**
239
     * Get the mime-type of a given file.
240
     *
241
     * @param  string $path
242
     * @return string|false
243
     */
244 3
    public function mimeType($path)
245
    {
246 3
        return finfo_file(finfo_open(FILEINFO_MIME_TYPE), $path);
247
    }
248
249
    /**
250
     * Get the file size of a given file.
251
     *
252
     * @param  string $path
253
     * @return int
254
     */
255 3
    public function size($path): int
256
    {
257 3
        return filesize($path);
258
    }
259
260
    /**
261
     * Get the file's last modification time.
262
     *
263
     * @param  string $path
264
     * @return int
265
     */
266 3
    public function lastModified($path): int
267
    {
268 3
        return filemtime($path);
269
    }
270
271
    /**
272
     * Determine if the given path is a directory.
273
     *
274
     * @param  string $directory
275
     * @return bool
276
     */
277 9
    public function isDirectory($directory): bool
278
    {
279 9
        return is_dir($directory);
280
    }
281
282
    /**
283
     * Determine if the given path is readable.
284
     *
285
     * @param  string $path
286
     * @return bool
287
     */
288 9
    public function isReadable($path): bool
289
    {
290 9
        return is_readable($path);
291
    }
292
293
    /**
294
     * Determine if the given path is writable.
295
     *
296
     * @param  string $path
297
     * @return bool
298
     */
299 9
    public function isWritable($path): bool
300
    {
301 9
        return is_writable($path);
302
    }
303
304
    /**
305
     * Determine if the given path is a file.
306
     *
307
     * @param  string $file
308
     * @return bool
309
     */
310 9
    public function isFile($file): bool
311
    {
312 9
        return is_file($file);
313
    }
314
315
    /**
316
     * Create a directory.
317
     *
318
     * @param  string $path
319
     * @param  int    $mode
320
     * @param  bool   $recursive
321
     * @param  bool   $force
322
     * @return bool
323
     */
324 9
    public function makeDirectory($path, $mode = 0755, $recursive = false, $force = false): bool
325
    {
326 9
        if ($force) {
327 6
            return @mkdir($path, $mode, $recursive);
328
        }
329
330 6
        return mkdir($path, $mode, $recursive);
331
    }
332
333
    /**
334
     * Move a directory.
335
     *
336
     * @param  string $from
337
     * @param  string $to
338
     * @param  bool   $overwrite
339
     * @return bool
340
     */
341 6
    public function moveDirectory($from, $to, $overwrite = false): bool
342
    {
343 6
        if ($overwrite && $this->isDirectory($to) && !$this->deleteDirectory($to)) {
344
            return false;
345
        }
346
347 6
        return @rename($from, $to) === true;
348
    }
349
350
    /**
351
     * Copy a directory from one location to another.
352
     *
353
     * @param  string $directory
354
     * @param  string $destination
355
     * @param  int    $options
356
     * @return bool
357
     */
358 6
    public function copyDirectory($directory, $destination, $options = null): bool
359
    {
360 6
        if (!$this->isDirectory($directory)) {
361
            return false;
362
        }
363
364 6
        $options = $options ?: FilesystemIterator::SKIP_DOTS;
365
366 6
        if (!$this->isDirectory($destination)) {
367 6
            $this->makeDirectory($destination, 0777, true);
368
        }
369
370 6
        $items = new FilesystemIterator($directory, $options);
371
372 6
        foreach ($items as $item) {
373 3
            $target = $destination . '/' . $item->getBasename();
374
375 3
            if (!$item->isDir()) {
376
                if (!$this->copy($item->getPathname(), $target)) {
377
                    return false;
378
                }
379
            } else {
380 3
                $path = $item->getPathname();
381
382 3
                if (!$this->copyDirectory($path, $target, $options)) {
383 2
                    return false;
384
                }
385
            }
386
        }
387
388 6
        return true;
389
    }
390
391
    /**
392
     * Recursively delete a directory.
393
     *
394
     * The directory itself may be optionally preserved.
395
     *
396
     * @param  string $directory
397
     * @param  bool   $preserve
398
     * @return bool
399
     */
400 9
    public function deleteDirectory($directory, $preserve = false): bool
401
    {
402 9
        if (!$this->isDirectory($directory)) {
403 3
            return false;
404
        }
405
406 9
        $items = new FilesystemIterator($directory);
407
408 9
        foreach ($items as $item) {
409 6
            if ($item->isDir() && !$item->isLink()) {
410 6
                $this->deleteDirectory($item->getPathname());
411
            } else {
412 5
                $this->delete($item->getPathname());
413
            }
414
        }
415
416 9
        if (!$preserve) {
417 9
            /** @scrutinizer ignore-unhandled */ @rmdir($directory);
418
        }
419
420 9
        return true;
421
    }
422
423
    /**
424
     * Empty the specified directory of all files and folders.
425
     *
426
     * @param  string $directory
427
     * @return bool
428
     */
429 3
    public function cleanDirectory($directory): bool
430
    {
431 3
        return $this->deleteDirectory($directory, true);
432
    }
433
434
    /**
435
     * Determine whether the current environment is Windows based.
436
     *
437
     * @return bool
438
     */
439 3
    public function windowsOs(): bool
440
    {
441 3
        return stripos(PHP_OS, 'win') === 0;
442
    }
443
}
444