|
0
|
1 |
<?php |
|
|
2 |
|
|
|
3 |
/* |
|
|
4 |
* This file is part of the Symfony package. |
|
|
5 |
* |
|
|
6 |
* (c) Fabien Potencier <fabien@symfony.com> |
|
|
7 |
* |
|
|
8 |
* For the full copyright and license information, please view the LICENSE |
|
|
9 |
* file that was distributed with this source code. |
|
|
10 |
*/ |
|
|
11 |
|
|
|
12 |
namespace Symfony\Component\HttpKernel\Util; |
|
|
13 |
|
|
|
14 |
/** |
|
|
15 |
* Provides basic utility to manipulate the file system. |
|
|
16 |
* |
|
|
17 |
* @author Fabien Potencier <fabien@symfony.com> |
|
|
18 |
*/ |
|
|
19 |
class Filesystem |
|
|
20 |
{ |
|
|
21 |
/** |
|
|
22 |
* Copies a file. |
|
|
23 |
* |
|
|
24 |
* This method only copies the file if the origin file is newer than the target file. |
|
|
25 |
* |
|
|
26 |
* By default, if the target already exists, it is not overridden. |
|
|
27 |
* |
|
|
28 |
* @param string $originFile The original filename |
|
|
29 |
* @param string $targetFile The target filename |
|
|
30 |
* @param array $override Whether to override an existing file or not |
|
|
31 |
*/ |
|
|
32 |
public function copy($originFile, $targetFile, $override = false) |
|
|
33 |
{ |
|
|
34 |
$this->mkdir(dirname($targetFile)); |
|
|
35 |
|
|
|
36 |
$mostRecent = false; |
|
|
37 |
if (file_exists($targetFile)) { |
|
|
38 |
$statTarget = stat($targetFile); |
|
|
39 |
$statOrigin = stat($originFile); |
|
|
40 |
$mostRecent = $statOrigin['mtime'] > $statTarget['mtime']; |
|
|
41 |
} |
|
|
42 |
|
|
|
43 |
if ($override || !file_exists($targetFile) || $mostRecent) { |
|
|
44 |
copy($originFile, $targetFile); |
|
|
45 |
} |
|
|
46 |
} |
|
|
47 |
|
|
|
48 |
/** |
|
|
49 |
* Creates a directory recursively. |
|
|
50 |
* |
|
|
51 |
* @param string|array|\Traversable $dirs The directory path |
|
|
52 |
* @param int $mode The directory mode |
|
|
53 |
* |
|
|
54 |
* @return Boolean true if the directory has been created, false otherwise |
|
|
55 |
*/ |
|
|
56 |
public function mkdir($dirs, $mode = 0777) |
|
|
57 |
{ |
|
|
58 |
$ret = true; |
|
|
59 |
foreach ($this->toIterator($dirs) as $dir) { |
|
|
60 |
if (is_dir($dir)) { |
|
|
61 |
continue; |
|
|
62 |
} |
|
|
63 |
|
|
|
64 |
$ret = @mkdir($dir, $mode, true) && $ret; |
|
|
65 |
} |
|
|
66 |
|
|
|
67 |
return $ret; |
|
|
68 |
} |
|
|
69 |
|
|
|
70 |
/** |
|
|
71 |
* Creates empty files. |
|
|
72 |
* |
|
|
73 |
* @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to remove |
|
|
74 |
*/ |
|
|
75 |
public function touch($files) |
|
|
76 |
{ |
|
|
77 |
foreach ($this->toIterator($files) as $file) { |
|
|
78 |
touch($file); |
|
|
79 |
} |
|
|
80 |
} |
|
|
81 |
|
|
|
82 |
/** |
|
|
83 |
* Removes files or directories. |
|
|
84 |
* |
|
|
85 |
* @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to remove |
|
|
86 |
*/ |
|
|
87 |
public function remove($files) |
|
|
88 |
{ |
|
|
89 |
$files = iterator_to_array($this->toIterator($files)); |
|
|
90 |
$files = array_reverse($files); |
|
|
91 |
foreach ($files as $file) { |
|
|
92 |
if (!file_exists($file)) { |
|
|
93 |
continue; |
|
|
94 |
} |
|
|
95 |
|
|
|
96 |
if (is_dir($file) && !is_link($file)) { |
|
|
97 |
$this->remove(new \FilesystemIterator($file)); |
|
|
98 |
|
|
|
99 |
rmdir($file); |
|
|
100 |
} else { |
|
|
101 |
unlink($file); |
|
|
102 |
} |
|
|
103 |
} |
|
|
104 |
} |
|
|
105 |
|
|
|
106 |
/** |
|
|
107 |
* Change mode for an array of files or directories. |
|
|
108 |
* |
|
|
109 |
* @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to remove |
|
|
110 |
* @param integer $mode The new mode |
|
|
111 |
* @param integer $umask The mode mask (octal) |
|
|
112 |
*/ |
|
|
113 |
public function chmod($files, $mode, $umask = 0000) |
|
|
114 |
{ |
|
|
115 |
$currentUmask = umask(); |
|
|
116 |
umask($umask); |
|
|
117 |
|
|
|
118 |
foreach ($this->toIterator($files) as $file) { |
|
|
119 |
chmod($file, $mode); |
|
|
120 |
} |
|
|
121 |
|
|
|
122 |
umask($currentUmask); |
|
|
123 |
} |
|
|
124 |
|
|
|
125 |
/** |
|
|
126 |
* Renames a file. |
|
|
127 |
* |
|
|
128 |
* @param string $origin The origin filename |
|
|
129 |
* @param string $target The new filename |
|
|
130 |
* |
|
|
131 |
* @throws \RuntimeException When target file already exists |
|
|
132 |
*/ |
|
|
133 |
public function rename($origin, $target) |
|
|
134 |
{ |
|
|
135 |
// we check that target does not exist |
|
|
136 |
if (is_readable($target)) { |
|
|
137 |
throw new \RuntimeException(sprintf('Cannot rename because the target "%" already exist.', $target)); |
|
|
138 |
} |
|
|
139 |
|
|
|
140 |
rename($origin, $target); |
|
|
141 |
} |
|
|
142 |
|
|
|
143 |
/** |
|
|
144 |
* Creates a symbolic link or copy a directory. |
|
|
145 |
* |
|
|
146 |
* @param string $originDir The origin directory path |
|
|
147 |
* @param string $targetDir The symbolic link name |
|
|
148 |
* @param Boolean $copyOnWindows Whether to copy files if on windows |
|
|
149 |
*/ |
|
|
150 |
public function symlink($originDir, $targetDir, $copyOnWindows = false) |
|
|
151 |
{ |
|
|
152 |
if (!function_exists('symlink') && $copyOnWindows) { |
|
|
153 |
$this->mirror($originDir, $targetDir); |
|
|
154 |
|
|
|
155 |
return; |
|
|
156 |
} |
|
|
157 |
|
|
|
158 |
$ok = false; |
|
|
159 |
if (is_link($targetDir)) { |
|
|
160 |
if (readlink($targetDir) != $originDir) { |
|
|
161 |
unlink($targetDir); |
|
|
162 |
} else { |
|
|
163 |
$ok = true; |
|
|
164 |
} |
|
|
165 |
} |
|
|
166 |
|
|
|
167 |
if (!$ok) { |
|
|
168 |
symlink($originDir, $targetDir); |
|
|
169 |
} |
|
|
170 |
} |
|
|
171 |
|
|
|
172 |
/** |
|
|
173 |
* Mirrors a directory to another. |
|
|
174 |
* |
|
|
175 |
* @param string $originDir The origin directory |
|
|
176 |
* @param string $targetDir The target directory |
|
|
177 |
* @param \Traversable $iterator A Traversable instance |
|
|
178 |
* @param array $options An array of options (see copy()) |
|
|
179 |
* |
|
|
180 |
* @throws \RuntimeException When file type is unknown |
|
|
181 |
*/ |
|
|
182 |
public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array()) |
|
|
183 |
{ |
|
|
184 |
if (null === $iterator) { |
|
|
185 |
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST); |
|
|
186 |
} |
|
|
187 |
|
|
|
188 |
if ('/' === substr($targetDir, -1) || '\\' === substr($targetDir, -1)) { |
|
|
189 |
$targetDir = substr($targetDir, 0, -1); |
|
|
190 |
} |
|
|
191 |
|
|
|
192 |
if ('/' === substr($originDir, -1) || '\\' === substr($originDir, -1)) { |
|
|
193 |
$originDir = substr($originDir, 0, -1); |
|
|
194 |
} |
|
|
195 |
|
|
|
196 |
foreach ($iterator as $file) { |
|
|
197 |
$target = $targetDir.'/'.str_replace($originDir.DIRECTORY_SEPARATOR, '', $file->getPathname()); |
|
|
198 |
|
|
|
199 |
if (is_dir($file)) { |
|
|
200 |
$this->mkdir($target); |
|
|
201 |
} else if (is_file($file)) { |
|
|
202 |
$this->copy($file, $target, $options); |
|
|
203 |
} else if (is_link($file)) { |
|
|
204 |
$this->symlink($file, $target); |
|
|
205 |
} else { |
|
|
206 |
throw new \RuntimeException(sprintf('Unable to guess "%s" file type.', $file)); |
|
|
207 |
} |
|
|
208 |
} |
|
|
209 |
} |
|
|
210 |
|
|
|
211 |
/** |
|
|
212 |
* Returns whether the file path is an absolute path. |
|
|
213 |
* |
|
|
214 |
* @param string $file A file path |
|
|
215 |
* |
|
|
216 |
* @return Boolean |
|
|
217 |
*/ |
|
|
218 |
public function isAbsolutePath($file) |
|
|
219 |
{ |
|
|
220 |
if ($file[0] == '/' || $file[0] == '\\' |
|
|
221 |
|| (strlen($file) > 3 && ctype_alpha($file[0]) |
|
|
222 |
&& $file[1] == ':' |
|
|
223 |
&& ($file[2] == '\\' || $file[2] == '/') |
|
|
224 |
) |
|
|
225 |
) { |
|
|
226 |
return true; |
|
|
227 |
} |
|
|
228 |
|
|
|
229 |
return false; |
|
|
230 |
} |
|
|
231 |
|
|
|
232 |
private function toIterator($files) |
|
|
233 |
{ |
|
|
234 |
if (!$files instanceof \Traversable) { |
|
|
235 |
$files = new \ArrayObject(is_array($files) ? $files : array($files)); |
|
|
236 |
} |
|
|
237 |
|
|
|
238 |
return $files; |
|
|
239 |
} |
|
|
240 |
} |