|
21 | 21 | */ |
22 | 22 | class Filesystem |
23 | 23 | { |
| 24 | + private static $lastError; |
| 25 | + |
24 | 26 | /** |
25 | 27 | * Copies a file. |
26 | 28 | * |
@@ -95,12 +97,11 @@ public function mkdir($dirs, $mode = 0777) |
95 | 97 | continue; |
96 | 98 | } |
97 | 99 |
|
98 | | - if (true !== @mkdir($dir, $mode, true)) { |
99 | | - $error = error_get_last(); |
| 100 | + if (!self::box('mkdir', $dir, $mode, true)) { |
100 | 101 | if (!is_dir($dir)) { |
101 | 102 | // The directory was not created by a concurrent process. Let's throw an exception with a developer friendly error message if we have one |
102 | | - if ($error) { |
103 | | - throw new IOException(sprintf('Failed to create "%s": %s.', $dir, $error['message']), 0, null, $dir); |
| 103 | + if (self::$lastError) { |
| 104 | + throw new IOException(sprintf('Failed to create "%s": %s.', $dir, self::$lastError), 0, null, $dir); |
104 | 105 | } |
105 | 106 | throw new IOException(sprintf('Failed to create "%s"', $dir), 0, null, $dir); |
106 | 107 | } |
@@ -169,20 +170,17 @@ public function remove($files) |
169 | 170 | foreach ($files as $file) { |
170 | 171 | if (is_link($file)) { |
171 | 172 | // See https://bugs.php.net/52176 |
172 | | - if (!@(unlink($file) || '\\' !== DIRECTORY_SEPARATOR || rmdir($file)) && file_exists($file)) { |
173 | | - $error = error_get_last(); |
174 | | - throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, $error['message'])); |
| 173 | + if (!(self::box('unlink', $file) || '\\' !== DIRECTORY_SEPARATOR || self::box('rmdir', $file)) && file_exists($file)) { |
| 174 | + throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, self::$lastError)); |
175 | 175 | } |
176 | 176 | } elseif (is_dir($file)) { |
177 | 177 | $this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS)); |
178 | 178 |
|
179 | | - if (!@rmdir($file) && file_exists($file)) { |
180 | | - $error = error_get_last(); |
181 | | - throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, $error['message'])); |
| 179 | + if (!self::box('rmdir', $file) && file_exists($file)) { |
| 180 | + throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, self::$lastError)); |
182 | 181 | } |
183 | | - } elseif (!@unlink($file) && file_exists($file)) { |
184 | | - $error = error_get_last(); |
185 | | - throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, $error['message'])); |
| 182 | + } elseif (!self::box('unlink', $file) && file_exists($file)) { |
| 183 | + throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, self::$lastError)); |
186 | 184 | } |
187 | 185 | } |
188 | 186 | } |
@@ -336,19 +334,16 @@ public function symlink($originDir, $targetDir, $copyOnWindows = false) |
336 | 334 |
|
337 | 335 | $this->mkdir(dirname($targetDir)); |
338 | 336 |
|
339 | | - $ok = false; |
340 | 337 | if (is_link($targetDir)) { |
341 | | - if (readlink($targetDir) != $originDir) { |
342 | | - $this->remove($targetDir); |
343 | | - } else { |
344 | | - $ok = true; |
| 338 | + if (readlink($targetDir) === $originDir) { |
| 339 | + return; |
345 | 340 | } |
| 341 | + $this->remove($targetDir); |
346 | 342 | } |
347 | 343 |
|
348 | | - if (!$ok && true !== @symlink($originDir, $targetDir)) { |
349 | | - $report = error_get_last(); |
350 | | - if (is_array($report)) { |
351 | | - if ('\\' === DIRECTORY_SEPARATOR && false !== strpos($report['message'], 'error code(1314)')) { |
| 344 | + if (!self::box('symlink', $originDir, $targetDir)) { |
| 345 | + if (null !== self::$lastError) { |
| 346 | + if ('\\' === DIRECTORY_SEPARATOR && false !== strpos(self::$lastError, 'error code(1314)')) { |
352 | 347 | throw new IOException('Unable to create symlink due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?', 0, null, $targetDir); |
353 | 348 | } |
354 | 349 | } |
@@ -646,4 +641,29 @@ private function getSchemeAndHierarchy($filename) |
646 | 641 |
|
647 | 642 | return 2 === count($components) ? array($components[0], $components[1]) : array(null, $components[0]); |
648 | 643 | } |
| 644 | + |
| 645 | + private static function box($func) |
| 646 | + { |
| 647 | + self::$lastError = null; |
| 648 | + \set_error_handler(__CLASS__.'::handleError'); |
| 649 | + try { |
| 650 | + $result = \call_user_func_array($func, \array_slice(\func_get_args(), 1)); |
| 651 | + \restore_error_handler(); |
| 652 | + |
| 653 | + return $result; |
| 654 | + } catch (\Throwable $e) { |
| 655 | + } catch (\Exception $e) { |
| 656 | + } |
| 657 | + \restore_error_handler(); |
| 658 | + |
| 659 | + throw $e; |
| 660 | + } |
| 661 | + |
| 662 | + /** |
| 663 | + * @internal |
| 664 | + */ |
| 665 | + public static function handleError($type, $msg) |
| 666 | + { |
| 667 | + self::$lastError = $msg; |
| 668 | + } |
649 | 669 | } |
0 commit comments