Passed
Push — master ( 4489d6...729fd7 )
by 世昌
01:46
created

DirectoryHelper::copy()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 9
nc 3
nop 4
dl 0
loc 13
rs 9.9666
c 0
b 0
f 0
1
<?php
2
namespace nebula\application\filesystem;
3
4
use RecursiveIteratorIterator;
5
use nebula\component\loader\Path;
6
use nebula\component\loader\PathTrait;
7
use nebula\application\filesystem\FileHelper;
8
9
/**
10
 * 文件夹辅助
11
 */
12
trait DirectoryHelper
13
{
14
    /**
15
     * 递归创建目录
16
     *
17
     * @param string $path
18
     * @param integer $mode
19
     * @return boolean
20
     */
21
    public static function makes(string $path, int $mode = 0777):bool
22
    {
23
        if (!is_dir($path)) {
24
            if (!static::makes(dirname($path), $mode)) {
25
                return false;
26
            }
27
            if (!static::make($path, $mode)) {
28
                return false;
29
            }
30
        }
31
        return true;
32
    }
33
34
    /**
35
     * 创建目录
36
     *
37
     * @param string $path
38
     * @param integer $mode
39
     * @return boolean
40
     */
41
    public static function make(string $path, int $mode):bool
42
    {
43
        if (\is_dir(\dirname($path)) && is_writable(dirname($path))) {
44
            $mk = mkdir($path, $mode);
45
            if ($mk) {
46
                chmod($path, $mode);
47
            }
48
            return $mk;
49
        }
50
        return false;
51
    }
52
53
    /**
54
     * 删除空目录
55
     *
56
     * @param string $path
57
     * @return boolean
58
     */
59
    public static function rm(string $path):bool
60
    {
61
        if (!is_writable($path)) {
62
            return false;
63
        }
64
        return rmdir($path);
65
    }
66
67
    /**
68
     * 删除非空目录
69
     *
70
     * @param string $path
71
     * @param string|null $regex
72
     * @return boolean
73
     */
74
    public static function rmdirs(string $path, ?string $regex = null):bool
75
    {
76
        foreach (static::read($path, false, $regex, true) as $subpath) {
77
            if (\is_dir($subpath)) {
78
                static::rmdirs($subpath, $regex);
79
            } elseif (is_file($subpath)) {
80
                FileHelper::delete($subpath);
81
            }
82
        }
83
        static::rm($path);
84
        return true;
85
    }
86
87
88
    /**
89
     * 读目录下文件
90
     *
91
     * @param string $path
92
     * @param boolean $recursive
93
     * @param string|null $regex
94
     * @param boolean $full
95
     * @return \Iterator
96
     */
97
    public static function readFiles(string $path, bool $recursive=false, ?string $regex=null, bool $full=true, int $mode = RecursiveIteratorIterator::LEAVES_ONLY) : \Iterator
98
    {
99
        $parent = Path::format($path);
100
        foreach (static::read($path, $recursive, $regex, false, $mode) as $subpath) {
101
            $path = $full?$subpath:$parent.DIRECTORY_SEPARATOR.$subpath;
102
            if (is_file($path)) {
103
                yield $subpath;
104
            }
105
        }
106
    }
107
108
    /**
109
     * 读目录下文件夹
110
     *
111
     * @param string $path
112
     * @param boolean $recursive
113
     * @param string|null $regex
114
     * @param boolean $full
115
     * @return \Iterator
116
     */
117
    public static function readDirs(string $path, bool $recursive=false, ?string $regex=null, bool $full=false, int $mode = RecursiveIteratorIterator::LEAVES_ONLY): \Iterator
118
    {
119
        $parent = Path::format($path);
120
        foreach (static::read($path, $recursive, $regex, false, $mode) as $subpath) {
121
            $path = $full?$subpath:$parent.DIRECTORY_SEPARATOR.$subpath;
122
            if (is_dir($path)) {
123
                yield $subpath;
124
            }
125
        }
126
    }
127
128
    /**
129
     * 读目录,包括文件,文件夹
130
     *
131
     * @param string $path
132
     * @param boolean $recursive
133
     * @param string|null $regex
134
     * @param boolean $full
135
     * @return \Iterator
136
     */
137
    public static function read(string $path, bool $recursive=false, ?string $regex=null, bool $full=true, int $mode = RecursiveIteratorIterator::LEAVES_ONLY): \Iterator
138
    {
139
        $directory = Path::format($path);
140
        if ($directory && \is_dir($directory)) {
141
            $it = static::buildIterator($directory, $recursive, $regex, $mode);
142
            foreach ($it as $key => $item) {
143
                if ($full) {
144
                    yield $key;
145
                } else {
146
                    yield static::cut($key, $directory);
147
                }
148
            }
149
        }
150
    }
151
    
152
153
    protected static function buildIterator(string $directory, bool $recursive=false, ?string $regex = null, int $mode): \Iterator
154
    {
155
        $it = new \RecursiveDirectoryIterator($directory, \RecursiveDirectoryIterator::SKIP_DOTS);
156
        if ($regex !== null) {
157
            $it = new \RecursiveRegexIterator($it, $regex);
158
        }
159
        if ($recursive) {
160
            $it = new \RecursiveIteratorIterator($it, $mode);
161
        }
162
        return $it;
163
    }
164
165
    /**
166
     * 截断部分目录
167
     *
168
     * @param string $path
169
     * @param string $basepath
170
     * @return string
171
     */
172
    public static function cut(string $path, string $basepath):string
173
    {
174
        $path =  PathTrait::toAbsolutePath($path);
175
        $basepath = PathTrait::toAbsolutePath($basepath);
176
        if (strpos($path, $basepath.DIRECTORY_SEPARATOR) === 0) {
177
            return substr($path, \strlen($basepath) + 1);
178
        }
179
        return $path;
180
    }
181
182
    /**
183
     * 复制文件
184
     *
185
     * @param string $path
186
     * @param string $toPath
187
     * @param string|null $regex
188
     * @param boolean $move
189
     * @return boolean
190
     */
191
    public static function copy(string $path, string $toPath, ?string $regex=null, bool $move = false):bool
192
    {
193
        $directory = Path::format($path);
194
        static::makes($toPath);
195
        if ($directory && \is_writable($toPath)) {
196
            foreach (static::read($directory, true, $regex, false, RecursiveIteratorIterator::CHILD_FIRST) as $subpath) {
197
                $srcpath = $directory.DIRECTORY_SEPARATOR.$subpath;
198
                $destpath = $toPath.DIRECTORY_SEPARATOR.$subpath;
199
                static::proccessPath($srcpath, $destpath, $move);
200
            }
201
            return true;
202
        }
203
        return false;
204
    }
205
206
    protected static function proccessPath(string $srcpath, string $destpath, bool $move)
207
    {
208
        if (is_dir($srcpath)) {
209
            static::makes($destpath);
210
            if ($move) {
211
                static::rm($srcpath);
212
            }
213
        } else {
214
            static::makes(dirname($destpath));
215
            FileHelper::copy($srcpath, $destpath);
216
            if ($move) {
217
                FileHelper::delete($srcpath);
218
            }
219
        }
220
    }
221
222
    /**
223
     * 移动文件
224
     *
225
     * @param string $path
226
     * @param string $toPath
227
     * @param string|null $regex
228
     * @return boolean
229
     */
230
    public static function move(string $path, string $toPath, ?string $regex=null):bool
231
    {
232
        return static::copy($path, $toPath, $regex, true);
233
    }
234
}
235