PluginProbe
Packeta / 2.0.9
Packeta v2.0.9
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 / deps / nette / utils / src / Utils / FileSystem.php

FileSystem.php in Packeta 2.0.9, at deps/nette/utils/src/Utils/FileSystem.php

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