N°8834 - Add compatibility with PHP 8.4 (#819)

* N°8834 - Add compatibility with PHP 8.4

* Rollback of scssphp/scssphp version upgrade due to compilation error
This commit is contained in:
Lenaick
2026-02-26 10:36:32 +01:00
committed by GitHub
parent d4821b7edc
commit fc967c06ce
961 changed files with 12298 additions and 7130 deletions

View File

@@ -40,25 +40,25 @@ class Filesystem
{
$originIsLocal = stream_is_local($originFile) || 0 === stripos($originFile, 'file://');
if ($originIsLocal && !is_file($originFile)) {
throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile);
throw new FileNotFoundException(\sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile);
}
$this->mkdir(\dirname($targetFile));
$doCopy = true;
if (!$overwriteNewerFiles && null === parse_url($originFile, \PHP_URL_HOST) && is_file($targetFile)) {
if (!$overwriteNewerFiles && !parse_url($originFile, \PHP_URL_HOST) && is_file($targetFile)) {
$doCopy = filemtime($originFile) > filemtime($targetFile);
}
if ($doCopy) {
// https://bugs.php.net/64634
if (!$source = self::box('fopen', $originFile, 'r')) {
throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading: ', $originFile, $targetFile).self::$lastError, 0, null, $originFile);
throw new IOException(\sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading: ', $originFile, $targetFile).self::$lastError, 0, null, $originFile);
}
// Stream context created to allow files overwrite when using FTP stream wrapper - disabled by default
if (!$target = self::box('fopen', $targetFile, 'w', false, stream_context_create(['ftp' => ['overwrite' => true]]))) {
throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing: ', $originFile, $targetFile).self::$lastError, 0, null, $originFile);
throw new IOException(\sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing: ', $originFile, $targetFile).self::$lastError, 0, null, $originFile);
}
$bytesCopied = stream_copy_to_stream($source, $target);
@@ -67,15 +67,18 @@ class Filesystem
unset($source, $target);
if (!is_file($targetFile)) {
throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile);
throw new IOException(\sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile);
}
if ($originIsLocal) {
// 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);
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);
}
}
}
@@ -96,7 +99,7 @@ class Filesystem
}
if (!self::box('mkdir', $dir, $mode, true) && !is_dir($dir)) {
throw new IOException(sprintf('Failed to create "%s": ', $dir).self::$lastError, 0, null, $dir);
throw new IOException(\sprintf('Failed to create "%s": ', $dir).self::$lastError, 0, null, $dir);
}
}
}
@@ -110,7 +113,7 @@ class Filesystem
foreach ($this->toIterable($files) as $file) {
if (\strlen($file) > $maxPathLength) {
throw new IOException(sprintf('Could not check if file exist because path length exceeds %d characters.', $maxPathLength), 0, null, $file);
throw new IOException(\sprintf('Could not check if file exist because path length exceeds %d characters.', $maxPathLength), 0, null, $file);
}
if (!file_exists($file)) {
@@ -131,11 +134,11 @@ class Filesystem
*
* @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)
{
foreach ($this->toIterable($files) as $file) {
if (!($time ? self::box('touch', $file, $time, $atime) : self::box('touch', $file))) {
throw new IOException(sprintf('Failed to touch "%s": ', $file).self::$lastError, 0, null, $file);
throw new IOException(\sprintf('Failed to touch "%s": ', $file).self::$lastError, 0, null, $file);
}
}
}
@@ -165,11 +168,11 @@ class Filesystem
if (is_link($file)) {
// See https://bugs.php.net/52176
if (!(self::box('unlink', $file) || '\\' !== \DIRECTORY_SEPARATOR || self::box('rmdir', $file)) && file_exists($file)) {
throw new IOException(sprintf('Failed to remove symlink "%s": ', $file).self::$lastError);
throw new IOException(\sprintf('Failed to remove symlink "%s": ', $file).self::$lastError);
}
} 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 {
@@ -196,10 +199,10 @@ class Filesystem
$file = $origFile;
}
throw new IOException(sprintf('Failed to remove directory "%s": ', $file).$lastError);
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))) {
throw new IOException(sprintf('Failed to remove file "%s": ', $file).self::$lastError);
} 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);
}
}
}
@@ -219,7 +222,7 @@ class Filesystem
{
foreach ($this->toIterable($files) as $file) {
if (!self::box('chmod', $file, $mode & ~$umask)) {
throw new IOException(sprintf('Failed to chmod file "%s": ', $file).self::$lastError, 0, null, $file);
throw new IOException(\sprintf('Failed to chmod file "%s": ', $file).self::$lastError, 0, null, $file);
}
if ($recursive && is_dir($file) && !is_link($file)) {
$this->chmod(new \FilesystemIterator($file), $mode, $umask, true);
@@ -230,6 +233,10 @@ 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://php.net/chown
*
* @param string|int $user A user name or number
* @param bool $recursive Whether change the owner recursively or not
*
@@ -245,11 +252,11 @@ class Filesystem
}
if (is_link($file) && \function_exists('lchown')) {
if (!self::box('lchown', $file, $user)) {
throw new IOException(sprintf('Failed to chown file "%s": ', $file).self::$lastError, 0, null, $file);
throw new IOException(\sprintf('Failed to chown file "%s": ', $file).self::$lastError, 0, null, $file);
}
} else {
if (!self::box('chown', $file, $user)) {
throw new IOException(sprintf('Failed to chown file "%s": ', $file).self::$lastError, 0, null, $file);
throw new IOException(\sprintf('Failed to chown file "%s": ', $file).self::$lastError, 0, null, $file);
}
}
}
@@ -258,6 +265,10 @@ 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://php.net/chgrp
*
* @param string|int $group A group name or number
* @param bool $recursive Whether change the group recursively or not
*
@@ -273,11 +284,11 @@ class Filesystem
}
if (is_link($file) && \function_exists('lchgrp')) {
if (!self::box('lchgrp', $file, $group)) {
throw new IOException(sprintf('Failed to chgrp file "%s": ', $file).self::$lastError, 0, null, $file);
throw new IOException(\sprintf('Failed to chgrp file "%s": ', $file).self::$lastError, 0, null, $file);
}
} else {
if (!self::box('chgrp', $file, $group)) {
throw new IOException(sprintf('Failed to chgrp file "%s": ', $file).self::$lastError, 0, null, $file);
throw new IOException(\sprintf('Failed to chgrp file "%s": ', $file).self::$lastError, 0, null, $file);
}
}
}
@@ -295,7 +306,7 @@ class Filesystem
{
// we check that target does not exist
if (!$overwrite && $this->isReadable($target)) {
throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target);
throw new IOException(\sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target);
}
if (!self::box('rename', $origin, $target)) {
@@ -306,7 +317,7 @@ class Filesystem
return;
}
throw new IOException(sprintf('Cannot rename "%s" to "%s": ', $origin, $target).self::$lastError, 0, null, $target);
throw new IOException(\sprintf('Cannot rename "%s" to "%s": ', $origin, $target).self::$lastError, 0, null, $target);
}
}
@@ -320,7 +331,7 @@ class Filesystem
$maxPathLength = \PHP_MAXPATHLEN - 2;
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);
throw new IOException(\sprintf('Could not check if file is readable because path length exceeds %d characters.', $maxPathLength), 0, null, $filename);
}
return is_readable($filename);
@@ -381,7 +392,7 @@ class Filesystem
}
if (!is_file($originFile)) {
throw new FileNotFoundException(sprintf('Origin file "%s" is not a file.', $originFile));
throw new FileNotFoundException(\sprintf('Origin file "%s" is not a file.', $originFile));
}
foreach ($this->toIterable($targetFiles) as $targetFile) {
@@ -405,10 +416,10 @@ class Filesystem
{
if (self::$lastError) {
if ('\\' === \DIRECTORY_SEPARATOR && str_contains(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);
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);
}
}
throw new IOException(sprintf('Failed to create "%s" link from "%s" to "%s": ', $linkType, $origin, $target).self::$lastError, 0, null, $target);
throw new IOException(\sprintf('Failed to create "%s" link from "%s" to "%s": ', $linkType, $origin, $target).self::$lastError, 0, null, $target);
}
/**
@@ -445,11 +456,11 @@ class Filesystem
public function makePathRelative(string $endPath, string $startPath): string
{
if (!$this->isAbsolutePath($startPath)) {
throw new InvalidArgumentException(sprintf('The start path "%s" is not absolute.', $startPath));
throw new InvalidArgumentException(\sprintf('The start path "%s" is not absolute.', $startPath));
}
if (!$this->isAbsolutePath($endPath)) {
throw new InvalidArgumentException(sprintf('The end path "%s" is not absolute.', $endPath));
throw new InvalidArgumentException(\sprintf('The end path "%s" is not absolute.', $endPath));
}
// Normalize separators on Windows
@@ -530,14 +541,14 @@ class Filesystem
*
* @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 = [])
{
$targetDir = rtrim($targetDir, '/\\');
$originDir = rtrim($originDir, '/\\');
$originDirLen = \strlen($originDir);
if (!$this->exists($originDir)) {
throw new IOException(sprintf('The origin directory specified "%s" was not found.', $originDir), 0, null, $originDir);
throw new IOException(\sprintf('The origin directory specified "%s" was not found.', $originDir), 0, null, $originDir);
}
// Iterate in destination folder to remove obsolete entries
@@ -581,7 +592,7 @@ class Filesystem
} elseif (is_file($file)) {
$this->copy($file, $target, $options['override'] ?? false);
} else {
throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
throw new IOException(\sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
}
}
}
@@ -659,7 +670,7 @@ class Filesystem
public function dumpFile(string $filename, $content)
{
if (\is_array($content)) {
throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be string or resource, array given.', __METHOD__));
throw new \TypeError(\sprintf('Argument 2 passed to "%s()" must be string or resource, array given.', __METHOD__));
}
$dir = \dirname($filename);
@@ -680,14 +691,18 @@ class Filesystem
try {
if (false === self::box('file_put_contents', $tmpFile, $content)) {
throw new IOException(sprintf('Failed to write file "%s": ', $filename).self::$lastError, 0, null, $filename);
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);
}
}
@@ -706,7 +721,7 @@ class Filesystem
public function appendToFile(string $filename, $content/* , bool $lock = false */)
{
if (\is_array($content)) {
throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be string or resource, array given.', __METHOD__));
throw new \TypeError(\sprintf('Argument 2 passed to "%s()" must be string or resource, array given.', __METHOD__));
}
$dir = \dirname($filename);
@@ -718,7 +733,7 @@ class Filesystem
$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);
throw new IOException(\sprintf('Failed to write file "%s": ', $filename).self::$lastError, 0, null, $filename);
}
}
@@ -740,7 +755,7 @@ class Filesystem
private static function assertFunctionExists(string $func): void
{
if (!\function_exists($func)) {
throw new IOException(sprintf('Unable to perform filesystem operation because the "%s()" function has been disabled.', $func));
throw new IOException(\sprintf('Unable to perform filesystem operation because the "%s()" function has been disabled.', $func));
}
}