Pull merge.
[yaffs-website] / vendor / symfony / filesystem / Filesystem.php
index 50d7dcb4af145f12a856caaa322d3b18e5b33337..08151cbf8cfa1555795ed3bf8f57bb9244172ada 100644 (file)
@@ -11,8 +11,8 @@
 
 namespace Symfony\Component\Filesystem;
 
-use Symfony\Component\Filesystem\Exception\IOException;
 use Symfony\Component\Filesystem\Exception\FileNotFoundException;
+use Symfony\Component\Filesystem\Exception\IOException;
 
 /**
  * Provides basic utility to manipulate the file system.
@@ -21,6 +21,8 @@ use Symfony\Component\Filesystem\Exception\FileNotFoundException;
  */
 class Filesystem
 {
+    private static $lastError;
+
     /**
      * Copies a file.
      *
@@ -42,7 +44,7 @@ class Filesystem
             throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile);
         }
 
-        $this->mkdir(dirname($targetFile));
+        $this->mkdir(\dirname($targetFile));
 
         $doCopy = true;
         if (!$overwriteNewerFiles && null === parse_url($originFile, PHP_URL_HOST) && is_file($targetFile)) {
@@ -95,12 +97,11 @@ class Filesystem
                 continue;
             }
 
-            if (true !== @mkdir($dir, $mode, true)) {
-                $error = error_get_last();
+            if (!self::box('mkdir', $dir, $mode, true)) {
                 if (!is_dir($dir)) {
                     // The directory was not created by a concurrent process. Let's throw an exception with a developer friendly error message if we have one
-                    if ($error) {
-                        throw new IOException(sprintf('Failed to create "%s": %s.', $dir, $error['message']), 0, null, $dir);
+                    if (self::$lastError) {
+                        throw new IOException(sprintf('Failed to create "%s": %s.', $dir, self::$lastError), 0, null, $dir);
                     }
                     throw new IOException(sprintf('Failed to create "%s"', $dir), 0, null, $dir);
                 }
@@ -120,7 +121,7 @@ class Filesystem
         $maxPathLength = PHP_MAXPATHLEN - 2;
 
         foreach ($this->toIterable($files) as $file) {
-            if (strlen($file) > $maxPathLength) {
+            if (\strlen($file) > $maxPathLength) {
                 throw new IOException(sprintf('Could not check if file exist because path length exceeds %d characters.', $maxPathLength), 0, null, $file);
             }
 
@@ -162,27 +163,24 @@ class Filesystem
     {
         if ($files instanceof \Traversable) {
             $files = iterator_to_array($files, false);
-        } elseif (!is_array($files)) {
+        } elseif (!\is_array($files)) {
             $files = array($files);
         }
         $files = array_reverse($files);
         foreach ($files as $file) {
             if (is_link($file)) {
                 // See https://bugs.php.net/52176
-                if (!@(unlink($file) || '\\' !== DIRECTORY_SEPARATOR || rmdir($file)) && file_exists($file)) {
-                    $error = error_get_last();
-                    throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, $error['message']));
+                if (!(self::box('unlink', $file) || '\\' !== \DIRECTORY_SEPARATOR || self::box('rmdir', $file)) && file_exists($file)) {
+                    throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, self::$lastError));
                 }
             } elseif (is_dir($file)) {
                 $this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS));
 
-                if (!@rmdir($file) && file_exists($file)) {
-                    $error = error_get_last();
-                    throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, $error['message']));
+                if (!self::box('rmdir', $file) && file_exists($file)) {
+                    throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, self::$lastError));
                 }
-            } elseif (!@unlink($file) && file_exists($file)) {
-                $error = error_get_last();
-                throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, $error['message']));
+            } elseif (!self::box('unlink', $file) && file_exists($file)) {
+                throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, self::$lastError));
             }
         }
     }
@@ -224,7 +222,7 @@ class Filesystem
             if ($recursive && is_dir($file) && !is_link($file)) {
                 $this->chown(new \FilesystemIterator($file), $user, true);
             }
-            if (is_link($file) && function_exists('lchown')) {
+            if (is_link($file) && \function_exists('lchown')) {
                 if (true !== @lchown($file, $user)) {
                     throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
                 }
@@ -251,8 +249,8 @@ class Filesystem
             if ($recursive && is_dir($file) && !is_link($file)) {
                 $this->chgrp(new \FilesystemIterator($file), $group, true);
             }
-            if (is_link($file) && function_exists('lchgrp')) {
-                if (true !== @lchgrp($file, $group) || (defined('HHVM_VERSION') && !posix_getgrnam($group))) {
+            if (is_link($file) && \function_exists('lchgrp')) {
+                if (true !== @lchgrp($file, $group) || (\defined('HHVM_VERSION') && !posix_getgrnam($group))) {
                     throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
                 }
             } else {
@@ -305,7 +303,7 @@ class Filesystem
     {
         $maxPathLength = PHP_MAXPATHLEN - 2;
 
-        if (strlen($filename) > $maxPathLength) {
+        if (\strlen($filename) > $maxPathLength) {
             throw new IOException(sprintf('Could not check if file is readable because path length exceeds %d characters.', $maxPathLength), 0, null, $filename);
         }
 
@@ -323,7 +321,7 @@ class Filesystem
      */
     public function symlink($originDir, $targetDir, $copyOnWindows = false)
     {
-        if ('\\' === DIRECTORY_SEPARATOR) {
+        if ('\\' === \DIRECTORY_SEPARATOR) {
             $originDir = strtr($originDir, '/', '\\');
             $targetDir = strtr($targetDir, '/', '\\');
 
@@ -334,18 +332,16 @@ class Filesystem
             }
         }
 
-        $this->mkdir(dirname($targetDir));
+        $this->mkdir(\dirname($targetDir));
 
-        $ok = false;
         if (is_link($targetDir)) {
-            if (readlink($targetDir) != $originDir) {
-                $this->remove($targetDir);
-            } else {
-                $ok = true;
+            if (readlink($targetDir) === $originDir) {
+                return;
             }
+            $this->remove($targetDir);
         }
 
-        if (!$ok && true !== @symlink($originDir, $targetDir)) {
+        if (!self::box('symlink', $originDir, $targetDir)) {
             $this->linkException($originDir, $targetDir, 'symbolic');
         }
     }
@@ -377,7 +373,7 @@ class Filesystem
                 $this->remove($targetFile);
             }
 
-            if (true !== @link($originFile, $targetFile)) {
+            if (!self::box('link', $originFile, $targetFile)) {
                 $this->linkException($originFile, $targetFile, 'hard');
             }
         }
@@ -390,9 +386,8 @@ class Filesystem
      */
     private function linkException($origin, $target, $linkType)
     {
-        $report = error_get_last();
-        if (is_array($report)) {
-            if ('\\' === DIRECTORY_SEPARATOR && false !== strpos($report['message'], 'error code(1314)')) {
+        if (self::$lastError) {
+            if ('\\' === \DIRECTORY_SEPARATOR && false !== strpos(self::$lastError, 'error code(1314)')) {
                 throw new IOException(sprintf('Unable to create %s link due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?', $linkType), 0, null, $target);
             }
         }
@@ -426,14 +421,14 @@ class Filesystem
                 return;
             }
 
-            if ('\\' === DIRECTORY_SEPARATOR) {
+            if ('\\' === \DIRECTORY_SEPARATOR) {
                 $path = readlink($path);
             }
 
             return realpath($path);
         }
 
-        if ('\\' === DIRECTORY_SEPARATOR) {
+        if ('\\' === \DIRECTORY_SEPARATOR) {
             return realpath($path);
         }
 
@@ -455,13 +450,13 @@ class Filesystem
         }
 
         // Normalize separators on Windows
-        if ('\\' === DIRECTORY_SEPARATOR) {
+        if ('\\' === \DIRECTORY_SEPARATOR) {
             $endPath = str_replace('\\', '/', $endPath);
             $startPath = str_replace('\\', '/', $startPath);
         }
 
         $stripDriveLetter = function ($path) {
-            if (strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0])) {
+            if (\strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0])) {
                 return substr($path, 2);
             }
 
@@ -479,7 +474,7 @@ class Filesystem
             $result = array();
 
             foreach ($pathSegments as $segment) {
-                if ('..' === $segment && ($absolute || count($result))) {
+                if ('..' === $segment && ($absolute || \count($result))) {
                     array_pop($result);
                 } elseif ('.' !== $segment) {
                     $result[] = $segment;
@@ -499,16 +494,16 @@ class Filesystem
         }
 
         // Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels)
-        if (1 === count($startPathArr) && '' === $startPathArr[0]) {
+        if (1 === \count($startPathArr) && '' === $startPathArr[0]) {
             $depth = 0;
         } else {
-            $depth = count($startPathArr) - $index;
+            $depth = \count($startPathArr) - $index;
         }
 
         // Repeated "../" for each level need to reach the common path
         $traverser = str_repeat('../', $depth);
 
-        $endPathRemainder = implode('/', array_slice($endPathArr, $index));
+        $endPathRemainder = implode('/', \array_slice($endPathArr, $index));
 
         // Construct $endPath from traversing to the common path, then to the remaining $endPath
         $relativePath = $traverser.('' !== $endPathRemainder ? $endPathRemainder.'/' : '');
@@ -539,7 +534,7 @@ class Filesystem
     {
         $targetDir = rtrim($targetDir, '/\\');
         $originDir = rtrim($originDir, '/\\');
-        $originDirLen = strlen($originDir);
+        $originDirLen = \strlen($originDir);
 
         // Iterate in destination folder to remove obsolete entries
         if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) {
@@ -548,7 +543,7 @@ class Filesystem
                 $flags = \FilesystemIterator::SKIP_DOTS;
                 $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST);
             }
-            $targetDirLen = strlen($targetDir);
+            $targetDirLen = \strlen($targetDir);
             foreach ($deleteIterator as $file) {
                 $origin = $originDir.substr($file->getPathname(), $targetDirLen);
                 if (!$this->exists($origin)) {
@@ -606,7 +601,7 @@ class Filesystem
     public function isAbsolutePath($file)
     {
         return strspn($file, '/\\', 0, 1)
-            || (strlen($file) > 3 && ctype_alpha($file[0])
+            || (\strlen($file) > 3 && ctype_alpha($file[0])
                 && ':' === $file[1]
                 && strspn($file, '/\\', 2, 1)
             )
@@ -676,7 +671,7 @@ class Filesystem
      */
     public function dumpFile($filename, $content)
     {
-        $dir = dirname($filename);
+        $dir = \dirname($filename);
 
         if (!is_dir($dir)) {
             $this->mkdir($dir);
@@ -709,7 +704,7 @@ class Filesystem
      */
     public function appendToFile($filename, $content)
     {
-        $dir = dirname($filename);
+        $dir = \dirname($filename);
 
         if (!is_dir($dir)) {
             $this->mkdir($dir);
@@ -731,7 +726,7 @@ class Filesystem
      */
     private function toIterable($files)
     {
-        return is_array($files) || $files instanceof \Traversable ? $files : array($files);
+        return \is_array($files) || $files instanceof \Traversable ? $files : array($files);
     }
 
     /**
@@ -745,6 +740,31 @@ class Filesystem
     {
         $components = explode('://', $filename, 2);
 
-        return 2 === count($components) ? array($components[0], $components[1]) : array(null, $components[0]);
+        return 2 === \count($components) ? array($components[0], $components[1]) : array(null, $components[0]);
+    }
+
+    private static function box($func)
+    {
+        self::$lastError = null;
+        \set_error_handler(__CLASS__.'::handleError');
+        try {
+            $result = \call_user_func_array($func, \array_slice(\func_get_args(), 1));
+            \restore_error_handler();
+
+            return $result;
+        } catch (\Throwable $e) {
+        } catch (\Exception $e) {
+        }
+        \restore_error_handler();
+
+        throw $e;
+    }
+
+    /**
+     * @internal
+     */
+    public static function handleError($type, $msg)
+    {
+        self::$lastError = $msg;
     }
 }