From 1bcfe90bea0f9ef86ca1e631e509e6ac0adc3c0f Mon Sep 17 00:00:00 2001 From: netkas Date: Tue, 17 Sep 2024 19:26:23 -0400 Subject: [PATCH] Updated Symfony/Filesystem from version 6.3.1 to 7.1.2 --- .../Symfony/Filesystem/CHANGELOG.md | 10 ++ .../Exception/FileNotFoundException.php | 2 +- .../Filesystem/Exception/IOException.php | 12 +-- .../Symfony/Filesystem/Filesystem.php | 96 ++++++++++--------- .../ThirdParty/Symfony/Filesystem/Path.php | 19 ++-- src/ncc/ThirdParty/Symfony/Filesystem/VERSION | 2 +- 6 files changed, 76 insertions(+), 65 deletions(-) diff --git a/src/ncc/ThirdParty/Symfony/Filesystem/CHANGELOG.md b/src/ncc/ThirdParty/Symfony/Filesystem/CHANGELOG.md index fcb7170..80818d1 100644 --- a/src/ncc/ThirdParty/Symfony/Filesystem/CHANGELOG.md +++ b/src/ncc/ThirdParty/Symfony/Filesystem/CHANGELOG.md @@ -1,6 +1,16 @@ CHANGELOG ========= +7.1 +--- + + * Add the `Filesystem::readFile()` method + +7.0 +--- + + * Add argument `$lock` to `Filesystem::appendToFile()` + 5.4 --- diff --git a/src/ncc/ThirdParty/Symfony/Filesystem/Exception/FileNotFoundException.php b/src/ncc/ThirdParty/Symfony/Filesystem/Exception/FileNotFoundException.php index 7908a84..e16e4e1 100644 --- a/src/ncc/ThirdParty/Symfony/Filesystem/Exception/FileNotFoundException.php +++ b/src/ncc/ThirdParty/Symfony/Filesystem/Exception/FileNotFoundException.php @@ -19,7 +19,7 @@ namespace ncc\ThirdParty\Symfony\Filesystem\Exception; */ class FileNotFoundException extends IOException { - public function __construct(string $message = null, int $code = 0, \Throwable $previous = null, string $path = null) + public function __construct(?string $message = null, int $code = 0, ?\Throwable $previous = null, ?string $path = null) { if (null === $message) { if (null === $path) { diff --git a/src/ncc/ThirdParty/Symfony/Filesystem/Exception/IOException.php b/src/ncc/ThirdParty/Symfony/Filesystem/Exception/IOException.php index b4272dc..caea8a6 100644 --- a/src/ncc/ThirdParty/Symfony/Filesystem/Exception/IOException.php +++ b/src/ncc/ThirdParty/Symfony/Filesystem/Exception/IOException.php @@ -20,12 +20,12 @@ namespace ncc\ThirdParty\Symfony\Filesystem\Exception; */ class IOException extends \RuntimeException implements IOExceptionInterface { - private ?string $path; - - public function __construct(string $message, int $code = 0, \Throwable $previous = null, string $path = null) - { - $this->path = $path; - + public function __construct( + string $message, + int $code = 0, + ?\Throwable $previous = null, + private ?string $path = null, + ) { parent::__construct($message, $code, $previous); } diff --git a/src/ncc/ThirdParty/Symfony/Filesystem/Filesystem.php b/src/ncc/ThirdParty/Symfony/Filesystem/Filesystem.php index 2cefc76..852ba12 100644 --- a/src/ncc/ThirdParty/Symfony/Filesystem/Filesystem.php +++ b/src/ncc/ThirdParty/Symfony/Filesystem/Filesystem.php @@ -22,7 +22,7 @@ use ncc\ThirdParty\Symfony\Filesystem\Exception\IOException; */ class Filesystem { - private static $lastError; + private static ?string $lastError = null; /** * Copies a file. @@ -31,12 +31,10 @@ class Filesystem * If the target file is newer, it is overwritten only when the * $overwriteNewerFiles option is set to true. * - * @return void - * * @throws FileNotFoundException When originFile doesn't exist * @throws IOException When copy fails */ - public function copy(string $originFile, string $targetFile, bool $overwriteNewerFiles = false) + public function copy(string $originFile, string $targetFile, bool $overwriteNewerFiles = false): void { $originIsLocal = stream_is_local($originFile) || 0 === stripos($originFile, 'file://'); if ($originIsLocal && !is_file($originFile)) { @@ -74,6 +72,9 @@ class Filesystem // Like `cp`, preserve executable permission bits self::box('chmod', $targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111)); + // Like `cp`, preserve the file modification time + self::box('touch', $targetFile, filemtime($originFile)); + if ($bytesCopied !== $bytesOrigin = filesize($originFile)) { throw new IOException(sprintf('Failed to copy the whole content of "%s" to "%s" (%g of %g bytes copied).', $originFile, $targetFile, $bytesCopied, $bytesOrigin), 0, null, $originFile); } @@ -84,11 +85,9 @@ class Filesystem /** * Creates a directory recursively. * - * @return void - * * @throws IOException On any directory creation failure */ - public function mkdir(string|iterable $dirs, int $mode = 0777) + public function mkdir(string|iterable $dirs, int $mode = 0777): void { foreach ($this->toIterable($dirs) as $dir) { if (is_dir($dir)) { @@ -127,11 +126,9 @@ class Filesystem * @param int|null $time The touch time as a Unix timestamp, if not supplied the current system time is used * @param int|null $atime The access time as a Unix timestamp, if not supplied the current system time is used * - * @return void - * * @throws IOException When touch fails */ - public function touch(string|iterable $files, int $time = null, int $atime = null) + public function touch(string|iterable $files, ?int $time = null, ?int $atime = null): void { foreach ($this->toIterable($files) as $file) { if (!($time ? self::box('touch', $file, $time, $atime) : self::box('touch', $file))) { @@ -143,11 +140,9 @@ class Filesystem /** * Removes files or directories. * - * @return void - * * @throws IOException When removal fails */ - public function remove(string|iterable $files) + public function remove(string|iterable $files): void { if ($files instanceof \Traversable) { $files = iterator_to_array($files, false); @@ -169,7 +164,7 @@ class Filesystem } } elseif (is_dir($file)) { if (!$isRecursive) { - $tmpName = \dirname(realpath($file)).'/.'.strrev(strtr(base64_encode(random_bytes(2)), '/=', '-_')); + $tmpName = \dirname(realpath($file)).'/.!'.strrev(strtr(base64_encode(random_bytes(2)), '/=', '-!')); if (file_exists($tmpName)) { try { @@ -198,7 +193,7 @@ class Filesystem throw new IOException(sprintf('Failed to remove directory "%s": ', $file).$lastError); } - } elseif (!self::box('unlink', $file) && (str_contains(self::$lastError, 'Permission denied') || file_exists($file))) { + } elseif (!self::box('unlink', $file) && ((self::$lastError && str_contains(self::$lastError, 'Permission denied')) || file_exists($file))) { throw new IOException(sprintf('Failed to remove file "%s": ', $file).self::$lastError); } } @@ -211,11 +206,9 @@ class Filesystem * @param int $umask The mode mask (octal) * @param bool $recursive Whether change the mod recursively or not * - * @return void - * * @throws IOException When the change fails */ - public function chmod(string|iterable $files, int $mode, int $umask = 0000, bool $recursive = false) + public function chmod(string|iterable $files, int $mode, int $umask = 0000, bool $recursive = false): void { foreach ($this->toIterable($files) as $file) { if (!self::box('chmod', $file, $mode & ~$umask)) { @@ -230,14 +223,15 @@ class Filesystem /** * Change the owner of an array of files or directories. * + * This method always throws on Windows, as the underlying PHP function is not supported. + * @see https://www.php.net/chown + * * @param string|int $user A user name or number * @param bool $recursive Whether change the owner recursively or not * - * @return void - * * @throws IOException When the change fails */ - public function chown(string|iterable $files, string|int $user, bool $recursive = false) + public function chown(string|iterable $files, string|int $user, bool $recursive = false): void { foreach ($this->toIterable($files) as $file) { if ($recursive && is_dir($file) && !is_link($file)) { @@ -258,14 +252,15 @@ class Filesystem /** * Change the group of an array of files or directories. * + * This method always throws on Windows, as the underlying PHP function is not supported. + * @see https://www.php.net/chgrp + * * @param string|int $group A group name or number * @param bool $recursive Whether change the group recursively or not * - * @return void - * * @throws IOException When the change fails */ - public function chgrp(string|iterable $files, string|int $group, bool $recursive = false) + public function chgrp(string|iterable $files, string|int $group, bool $recursive = false): void { foreach ($this->toIterable($files) as $file) { if ($recursive && is_dir($file) && !is_link($file)) { @@ -286,12 +281,10 @@ class Filesystem /** * Renames a file or a directory. * - * @return void - * * @throws IOException When target file or directory already exists * @throws IOException When origin cannot be renamed */ - public function rename(string $origin, string $target, bool $overwrite = false) + public function rename(string $origin, string $target, bool $overwrite = false): void { // we check that target does not exist if (!$overwrite && $this->isReadable($target)) { @@ -329,11 +322,9 @@ class Filesystem /** * Creates a symbolic link or copy a directory. * - * @return void - * * @throws IOException When symlink fails */ - public function symlink(string $originDir, string $targetDir, bool $copyOnWindows = false) + public function symlink(string $originDir, string $targetDir, bool $copyOnWindows = false): void { self::assertFunctionExists('symlink'); @@ -367,12 +358,10 @@ class Filesystem * * @param string|string[] $targetFiles The target file(s) * - * @return void - * * @throws FileNotFoundException When original file is missing or not a file * @throws IOException When link fails, including if link already exists */ - public function hardlink(string $originFile, string|iterable $targetFiles) + public function hardlink(string $originFile, string|iterable $targetFiles): void { self::assertFunctionExists('link'); @@ -526,11 +515,9 @@ class Filesystem * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink(), defaults to false) * - $options['delete'] Whether to delete files that are not in the source directory (defaults to false) * - * @return void - * * @throws IOException When file type is unknown */ - public function mirror(string $originDir, string $targetDir, \Traversable $iterator = null, array $options = []) + public function mirror(string $originDir, string $targetDir, ?\Traversable $iterator = null, array $options = []): void { $targetDir = rtrim($targetDir, '/\\'); $originDir = rtrim($originDir, '/\\'); @@ -652,11 +639,9 @@ class Filesystem * * @param string|resource $content The data to write into the file * - * @return void - * * @throws IOException if the file cannot be written to */ - public function dumpFile(string $filename, $content) + public function dumpFile(string $filename, $content): void { if (\is_array($content)) { throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be string or resource, array given.', __METHOD__)); @@ -683,11 +668,15 @@ class Filesystem throw new IOException(sprintf('Failed to write file "%s": ', $filename).self::$lastError, 0, null, $filename); } - self::box('chmod', $tmpFile, file_exists($filename) ? fileperms($filename) : 0666 & ~umask()); + self::box('chmod', $tmpFile, self::box('fileperms', $filename) ?: 0666 & ~umask()); $this->rename($tmpFile, $filename, true); } finally { if (file_exists($tmpFile)) { + if ('\\' === \DIRECTORY_SEPARATOR && !is_writable($tmpFile)) { + self::box('chmod', $tmpFile, self::box('fileperms', $tmpFile) | 0200); + } + self::box('unlink', $tmpFile); } } @@ -699,11 +688,9 @@ class Filesystem * @param string|resource $content The content to append * @param bool $lock Whether the file should be locked when writing to it * - * @return void - * * @throws IOException If the file is not writable */ - public function appendToFile(string $filename, $content/* , bool $lock = false */) + public function appendToFile(string $filename, $content, bool $lock = false): void { if (\is_array($content)) { throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be string or resource, array given.', __METHOD__)); @@ -715,13 +702,30 @@ class Filesystem $this->mkdir($dir); } - $lock = \func_num_args() > 2 && func_get_arg(2); - if (false === self::box('file_put_contents', $filename, $content, \FILE_APPEND | ($lock ? \LOCK_EX : 0))) { throw new IOException(sprintf('Failed to write file "%s": ', $filename).self::$lastError, 0, null, $filename); } } + /** + * Returns the content of a file as a string. + * + * @throws IOException If the file cannot be read + */ + public function readFile(string $filename): string + { + if (is_dir($filename)) { + throw new IOException(sprintf('Failed to read file "%s": File is a directory.', $filename)); + } + + $content = self::box('file_get_contents', $filename); + if (false === $content) { + throw new IOException(sprintf('Failed to read file "%s": ', $filename).self::$lastError, 0, null, $filename); + } + + return $content; + } + private function toIterable(string|iterable $files): iterable { return is_iterable($files) ? $files : [$files]; @@ -749,7 +753,7 @@ class Filesystem self::assertFunctionExists($func); self::$lastError = null; - set_error_handler(__CLASS__.'::handleError'); + set_error_handler(self::handleError(...)); try { return $func(...$args); } finally { diff --git a/src/ncc/ThirdParty/Symfony/Filesystem/Path.php b/src/ncc/ThirdParty/Symfony/Filesystem/Path.php index f936166..a55d328 100644 --- a/src/ncc/ThirdParty/Symfony/Filesystem/Path.php +++ b/src/ncc/ThirdParty/Symfony/Filesystem/Path.php @@ -42,12 +42,9 @@ final class Path * * @var array */ - private static $buffer = []; + private static array $buffer = []; - /** - * @var int - */ - private static $bufferSize = 0; + private static int $bufferSize = 0; /** * Canonicalizes the given path. @@ -257,7 +254,7 @@ final class Path * @param string|null $extension if specified, only that extension is cut * off (may contain leading dot) */ - public static function getFilenameWithoutExtension(string $path, string $extension = null): string + public static function getFilenameWithoutExtension(string $path, ?string $extension = null): string { if ('' === $path) { return ''; @@ -349,13 +346,13 @@ final class Path $extension = ltrim($extension, '.'); // No extension for paths - if ('/' === substr($path, -1)) { + if (str_ends_with($path, '/')) { return $path; } // No actual extension in path - if (empty($actualExtension)) { - return $path.('.' === substr($path, -1) ? '' : '.').$extension; + if (!$actualExtension) { + return $path.(str_ends_with($path, '.') ? '' : '.').$extension; } return substr($path, 0, -\strlen($actualExtension)).$extension; @@ -368,7 +365,7 @@ final class Path } // Strip scheme - if (false !== $schemeSeparatorPosition = strpos($path, '://')) { + if (false !== ($schemeSeparatorPosition = strpos($path, '://')) && 1 !== $schemeSeparatorPosition) { $path = substr($path, $schemeSeparatorPosition + 3); } @@ -671,7 +668,7 @@ final class Path } // Only add slash if previous part didn't end with '/' or '\' - if (!\in_array(substr($finalPath, -1), ['/', '\\'])) { + if (!\in_array(substr($finalPath, -1), ['/', '\\'], true)) { $finalPath .= '/'; } diff --git a/src/ncc/ThirdParty/Symfony/Filesystem/VERSION b/src/ncc/ThirdParty/Symfony/Filesystem/VERSION index 39ee137..0e7b60d 100644 --- a/src/ncc/ThirdParty/Symfony/Filesystem/VERSION +++ b/src/ncc/ThirdParty/Symfony/Filesystem/VERSION @@ -1 +1 @@ -6.3.1 \ No newline at end of file +7.1.2 \ No newline at end of file