1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Utils;
9:
10: use Nette;
11:
12:
13: 14: 15:
16: class FileSystem
17: {
18: use Nette\StaticClass;
19:
20: 21: 22: 23: 24:
25: public static function createDir($dir, $mode = 0777)
26: {
27: if (!is_dir($dir) && !@mkdir($dir, $mode, true) && !is_dir($dir)) {
28: throw new Nette\IOException("Unable to create directory '$dir'. " . self::getLastError());
29: }
30: }
31:
32:
33: 34: 35: 36: 37:
38: public static function copy($source, $dest, $overwrite = true)
39: {
40: if (stream_is_local($source) && !file_exists($source)) {
41: throw new Nette\IOException("File or directory '$source' not found.");
42:
43: } elseif (!$overwrite && file_exists($dest)) {
44: throw new Nette\InvalidStateException("File or directory '$dest' already exists.");
45:
46: } elseif (is_dir($source)) {
47: static::createDir($dest);
48: foreach (new \FilesystemIterator($dest) as $item) {
49: static::delete($item->getPathname());
50: }
51: foreach ($iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST) as $item) {
52: if ($item->isDir()) {
53: static::createDir($dest . '/' . $iterator->getSubPathName());
54: } else {
55: static::copy($item->getPathname(), $dest . '/' . $iterator->getSubPathName());
56: }
57: }
58:
59: } else {
60: static::createDir(dirname($dest));
61: if (@stream_copy_to_stream(fopen($source, 'r'), fopen($dest, 'w')) === false) {
62: throw new Nette\IOException("Unable to copy file '$source' to '$dest'. " . self::getLastError());
63: }
64: }
65: }
66:
67:
68: 69: 70: 71: 72:
73: public static function delete($path)
74: {
75: if (is_file($path) || is_link($path)) {
76: $func = DIRECTORY_SEPARATOR === '\\' && is_dir($path) ? 'rmdir' : 'unlink';
77: if (!@$func($path)) {
78: throw new Nette\IOException("Unable to delete '$path'. " . self::getLastError());
79: }
80:
81: } elseif (is_dir($path)) {
82: foreach (new \FilesystemIterator($path) as $item) {
83: static::delete($item->getPathname());
84: }
85: if (!@rmdir($path)) {
86: throw new Nette\IOException("Unable to delete directory '$path'. " . self::getLastError());
87: }
88: }
89: }
90:
91:
92: 93: 94: 95: 96: 97:
98: public static function rename($name, $newName, $overwrite = true)
99: {
100: if (!$overwrite && file_exists($newName)) {
101: throw new Nette\InvalidStateException("File or directory '$newName' already exists.");
102:
103: } elseif (!file_exists($name)) {
104: throw new Nette\IOException("File or directory '$name' not found.");
105:
106: } else {
107: static::createDir(dirname($newName));
108: if (realpath($name) !== realpath($newName)) {
109: static::delete($newName);
110: }
111: if (!@rename($name, $newName)) {
112: throw new Nette\IOException("Unable to rename file or directory '$name' to '$newName'. " . self::getLastError());
113: }
114: }
115: }
116:
117:
118: 119: 120: 121: 122:
123: public static function read($file)
124: {
125: $content = @file_get_contents($file);
126: if ($content === false) {
127: throw new Nette\IOException("Unable to read file '$file'. " . self::getLastError());
128: }
129: return $content;
130: }
131:
132:
133: 134: 135: 136: 137:
138: public static function write($file, $content, $mode = 0666)
139: {
140: static::createDir(dirname($file));
141: if (@file_put_contents($file, $content) === false) {
142: throw new Nette\IOException("Unable to write file '$file'. " . self::getLastError());
143: }
144: if ($mode !== null && !@chmod($file, $mode)) {
145: throw new Nette\IOException("Unable to chmod file '$file'. " . self::getLastError());
146: }
147: }
148:
149:
150: 151: 152: 153:
154: public static function isAbsolute($path)
155: {
156: return (bool) preg_match('#([a-z]:)?[/\\\\]|[a-z][a-z0-9+.-]*://#Ai', $path);
157: }
158:
159:
160: private static function getLastError()
161: {
162: return preg_replace('#^\w+\(.*?\): #', '', error_get_last()['message']);
163: }
164: }
165: