PluginProbe
Packeta / 1.3.2
Packeta v1.3.2
2.3.2 2.3.1 trunk 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.3.0 1.3.1 1.3.2 1.4 1.4.1 1.4.2 1.4.3 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 All 56 releases
packeta / packetery_vendor / nette / utils / src / Utils / FileSystem.php

FileSystem.php in Packeta 1.3.2, at packetery_vendor/nette/utils/src/Utils/FileSystem.php

211 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * This file is part of the PacketeryNette Framework (https://nette.org)
5 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6 */
7
8 declare(strict_types=1);
9
10 namespace PacketeryNette\Utils;
11
12 use PacketeryNette;
13
14
15 /**
16 * File system tool.
17 */
18 final class FileSystem
19 {
20 use PacketeryNette\StaticClass;
21
22 /**
23 * Creates a directory if it doesn't exist.
24 * @throws PacketeryNette\IOException on error occurred
25 */
26 public static function createDir(string $dir, int $mode = 0777): void
27 {
28 if (!is_dir($dir) && !@mkdir($dir, $mode, true) && !is_dir($dir)) { // @ - dir may already exist
29 throw new PacketeryNette\IOException("Unable to create directory '$dir' with mode " . decoct($mode) . '. ' . Helpers::getLastError());
30 }
31 }
32
33
34 /**
35 * Copies a file or a directory. Overwrites existing files and directories by default.
36 * @throws PacketeryNette\IOException on error occurred
37 * @throws PacketeryNette\InvalidStateException if $overwrite is set to false and destination already exists
38 */
39 public static function copy(string $origin, string $target, bool $overwrite = true): void
40 {
41 if (stream_is_local($origin) && !file_exists($origin)) {
42 throw new PacketeryNette\IOException("File or directory '$origin' not found.");
43
44 } elseif (!$overwrite && file_exists($target)) {
45 throw new PacketeryNette\InvalidStateException("File or directory '$target' already exists.");
46
47 } elseif (is_dir($origin)) {
48 static::createDir($target);
49 foreach (new \FilesystemIterator($target) as $item) {
50 static::delete($item->getPathname());
51 }
52 foreach ($iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($origin, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST) as $item) {
53 if ($item->isDir()) {
54 static::createDir($target . '/' . $iterator->getSubPathName());
55 } else {
56 static::copy($item->getPathname(), $target . '/' . $iterator->getSubPathName());
57 }
58 }
59
60 } else {
61 static::createDir(dirname($target));
62 if (
63 ($s = @fopen($origin, 'rb'))
64 && ($d = @fopen($target, 'wb'))
65 && @stream_copy_to_stream($s, $d) === false
66 ) { // @ is escalated to exception
67 throw new PacketeryNette\IOException("Unable to copy file '$origin' to '$target'. " . Helpers::getLastError());
68 }
69 }
70 }
71
72
73 /**
74 * Deletes a file or directory if exists.
75 * @throws PacketeryNette\IOException on error occurred
76 */
77 public static function delete(string $path): void
78 {
79 if (is_file($path) || is_link($path)) {
80 $func = DIRECTORY_SEPARATOR === '\\' && is_dir($path) ? 'rmdir' : 'unlink';
81 if (!@$func($path)) { // @ is escalated to exception
82 throw new PacketeryNette\IOException("Unable to delete '$path'. " . Helpers::getLastError());
83 }
84
85 } elseif (is_dir($path)) {
86 foreach (new \FilesystemIterator($path) as $item) {
87 static::delete($item->getPathname());
88 }
89 if (!@rmdir($path)) { // @ is escalated to exception
90 throw new PacketeryNette\IOException("Unable to delete directory '$path'. " . Helpers::getLastError());
91 }
92 }
93 }
94
95
96 /**
97 * Renames or moves a file or a directory. Overwrites existing files and directories by default.
98 * @throws PacketeryNette\IOException on error occurred
99 * @throws PacketeryNette\InvalidStateException if $overwrite is set to false and destination already exists
100 */
101 public static function rename(string $origin, string $target, bool $overwrite = true): void
102 {
103 if (!$overwrite && file_exists($target)) {
104 throw new PacketeryNette\InvalidStateException("File or directory '$target' already exists.");
105
106 } elseif (!file_exists($origin)) {
107 throw new PacketeryNette\IOException("File or directory '$origin' not found.");
108
109 } else {
110 static::createDir(dirname($target));
111 if (realpath($origin) !== realpath($target)) {
112 static::delete($target);
113 }
114 if (!@rename($origin, $target)) { // @ is escalated to exception
115 throw new PacketeryNette\IOException("Unable to rename file or directory '$origin' to '$target'. " . Helpers::getLastError());
116 }
117 }
118 }
119
120
121 /**
122 * Reads the content of a file.
123 * @throws PacketeryNette\IOException on error occurred
124 */
125 public static function read(string $file): string
126 {
127 $content = @file_get_contents($file); // @ is escalated to exception
128 if ($content === false) {
129 throw new PacketeryNette\IOException("Unable to read file '$file'. " . Helpers::getLastError());
130 }
131 return $content;
132 }
133
134
135 /**
136 * Writes the string to a file.
137 * @throws PacketeryNette\IOException on error occurred
138 */
139 public static function write(string $file, string $content, ?int $mode = 0666): void
140 {
141 static::createDir(dirname($file));
142 if (@file_put_contents($file, $content) === false) { // @ is escalated to exception
143 throw new PacketeryNette\IOException("Unable to write file '$file'. " . Helpers::getLastError());
144 }
145 if ($mode !== null && !@chmod($file, $mode)) { // @ is escalated to exception
146 throw new PacketeryNette\IOException("Unable to chmod file '$file' to mode " . decoct($mode) . '. ' . Helpers::getLastError());
147 }
148 }
149
150
151 /**
152 * Fixes permissions to a specific file or directory. Directories can be fixed recursively.
153 * @throws PacketeryNette\IOException on error occurred
154 */
155 public static function makeWritable(string $path, int $dirMode = 0777, int $fileMode = 0666): void
156 {
157 if (is_file($path)) {
158 if (!@chmod($path, $fileMode)) { // @ is escalated to exception
159 throw new PacketeryNette\IOException("Unable to chmod file '$path' to mode " . decoct($fileMode) . '. ' . Helpers::getLastError());
160 }
161 } elseif (is_dir($path)) {
162 foreach (new \FilesystemIterator($path) as $item) {
163 static::makeWritable($item->getPathname(), $dirMode, $fileMode);
164 }
165 if (!@chmod($path, $dirMode)) { // @ is escalated to exception
166 throw new PacketeryNette\IOException("Unable to chmod directory '$path' to mode " . decoct($dirMode) . '. ' . Helpers::getLastError());
167 }
168 } else {
169 throw new PacketeryNette\IOException("File or directory '$path' not found.");
170 }
171 }
172
173
174 /**
175 * Determines if the path is absolute.
176 */
177 public static function isAbsolute(string $path): bool
178 {
179 return (bool) preg_match('#([a-z]:)?[/\\\\]|[a-z][a-z0-9+.-]*://#Ai', $path);
180 }
181
182
183 /**
184 * Normalizes `..` and `.` and directory separators in path.
185 */
186 public static function normalizePath(string $path): string
187 {
188 $parts = $path === '' ? [] : preg_split('~[/\\\\]+~', $path);
189 $res = [];
190 foreach ($parts as $part) {
191 if ($part === '..' && $res && end($res) !== '..' && end($res) !== '') {
192 array_pop($res);
193 } elseif ($part !== '.') {
194 $res[] = $part;
195 }
196 }
197 return $res === ['']
198 ? DIRECTORY_SEPARATOR
199 : implode(DIRECTORY_SEPARATOR, $res);
200 }
201
202
203 /**
204 * Joins all segments of the path and normalizes the result.
205 */
206 public static function joinPaths(string ...$paths): string
207 {
208 return self::normalizePath(implode('/', $paths));
209 }
210 }
211