Add pear modules, mail and net_smtp via composer (#93)
Add pear modules, mail and net_smtp via composer, remove php 5.6 build due to phpunit 6
This commit is contained in:
@@ -37,7 +37,8 @@ class Filesystem
|
||||
*/
|
||||
public function copy($originFile, $targetFile, $overwriteNewerFiles = false)
|
||||
{
|
||||
if (stream_is_local($originFile) && !is_file($originFile)) {
|
||||
$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);
|
||||
}
|
||||
|
||||
@@ -68,11 +69,13 @@ class Filesystem
|
||||
throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile);
|
||||
}
|
||||
|
||||
// Like `cp`, preserve executable permission bits
|
||||
@chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111));
|
||||
if ($originIsLocal) {
|
||||
// Like `cp`, preserve executable permission bits
|
||||
@chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111));
|
||||
|
||||
if (stream_is_local($originFile) && $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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,14 +83,14 @@ class Filesystem
|
||||
/**
|
||||
* Creates a directory recursively.
|
||||
*
|
||||
* @param string|array|\Traversable $dirs The directory path
|
||||
* @param int $mode The directory mode
|
||||
* @param string|iterable $dirs The directory path
|
||||
* @param int $mode The directory mode
|
||||
*
|
||||
* @throws IOException On any directory creation failure
|
||||
*/
|
||||
public function mkdir($dirs, $mode = 0777)
|
||||
{
|
||||
foreach ($this->toIterator($dirs) as $dir) {
|
||||
foreach ($this->toIterable($dirs) as $dir) {
|
||||
if (is_dir($dir)) {
|
||||
continue;
|
||||
}
|
||||
@@ -108,15 +111,17 @@ class Filesystem
|
||||
/**
|
||||
* Checks the existence of files or directories.
|
||||
*
|
||||
* @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to check
|
||||
* @param string|iterable $files A filename, an array of files, or a \Traversable instance to check
|
||||
*
|
||||
* @return bool true if the file exists, false otherwise
|
||||
*/
|
||||
public function exists($files)
|
||||
{
|
||||
foreach ($this->toIterator($files) as $file) {
|
||||
if ('\\' === DIRECTORY_SEPARATOR && strlen($file) > 258) {
|
||||
throw new IOException('Could not check if file exist because path length exceeds 258 characters.', 0, null, $file);
|
||||
$maxPathLength = PHP_MAXPATHLEN - 2;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (!file_exists($file)) {
|
||||
@@ -130,15 +135,15 @@ class Filesystem
|
||||
/**
|
||||
* Sets access and modification time of file.
|
||||
*
|
||||
* @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to create
|
||||
* @param int $time The touch time as a Unix timestamp
|
||||
* @param int $atime The access time as a Unix timestamp
|
||||
* @param string|iterable $files A filename, an array of files, or a \Traversable instance to create
|
||||
* @param int $time The touch time as a Unix timestamp
|
||||
* @param int $atime The access time as a Unix timestamp
|
||||
*
|
||||
* @throws IOException When touch fails
|
||||
*/
|
||||
public function touch($files, $time = null, $atime = null)
|
||||
{
|
||||
foreach ($this->toIterator($files) as $file) {
|
||||
foreach ($this->toIterable($files) as $file) {
|
||||
$touch = $time ? @touch($file, $time, $atime) : @touch($file);
|
||||
if (true !== $touch) {
|
||||
throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file);
|
||||
@@ -149,7 +154,7 @@ class Filesystem
|
||||
/**
|
||||
* Removes files or directories.
|
||||
*
|
||||
* @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to remove
|
||||
* @param string|iterable $files A filename, an array of files, or a \Traversable instance to remove
|
||||
*
|
||||
* @throws IOException When removal fails
|
||||
*/
|
||||
@@ -185,16 +190,16 @@ class Filesystem
|
||||
/**
|
||||
* Change mode for an array of files or directories.
|
||||
*
|
||||
* @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change mode
|
||||
* @param int $mode The new mode (octal)
|
||||
* @param int $umask The mode mask (octal)
|
||||
* @param bool $recursive Whether change the mod recursively or not
|
||||
* @param string|iterable $files A filename, an array of files, or a \Traversable instance to change mode
|
||||
* @param int $mode The new mode (octal)
|
||||
* @param int $umask The mode mask (octal)
|
||||
* @param bool $recursive Whether change the mod recursively or not
|
||||
*
|
||||
* @throws IOException When the change fail
|
||||
*/
|
||||
public function chmod($files, $mode, $umask = 0000, $recursive = false)
|
||||
{
|
||||
foreach ($this->toIterator($files) as $file) {
|
||||
foreach ($this->toIterable($files) as $file) {
|
||||
if (true !== @chmod($file, $mode & ~$umask)) {
|
||||
throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file);
|
||||
}
|
||||
@@ -207,15 +212,15 @@ class Filesystem
|
||||
/**
|
||||
* Change the owner of an array of files or directories.
|
||||
*
|
||||
* @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change owner
|
||||
* @param string $user The new owner user name
|
||||
* @param bool $recursive Whether change the owner recursively or not
|
||||
* @param string|iterable $files A filename, an array of files, or a \Traversable instance to change owner
|
||||
* @param string $user The new owner user name
|
||||
* @param bool $recursive Whether change the owner recursively or not
|
||||
*
|
||||
* @throws IOException When the change fail
|
||||
*/
|
||||
public function chown($files, $user, $recursive = false)
|
||||
{
|
||||
foreach ($this->toIterator($files) as $file) {
|
||||
foreach ($this->toIterable($files) as $file) {
|
||||
if ($recursive && is_dir($file) && !is_link($file)) {
|
||||
$this->chown(new \FilesystemIterator($file), $user, true);
|
||||
}
|
||||
@@ -234,15 +239,15 @@ class Filesystem
|
||||
/**
|
||||
* Change the group of an array of files or directories.
|
||||
*
|
||||
* @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change group
|
||||
* @param string $group The group name
|
||||
* @param bool $recursive Whether change the group recursively or not
|
||||
* @param string|iterable $files A filename, an array of files, or a \Traversable instance to change group
|
||||
* @param string $group The group name
|
||||
* @param bool $recursive Whether change the group recursively or not
|
||||
*
|
||||
* @throws IOException When the change fail
|
||||
*/
|
||||
public function chgrp($files, $group, $recursive = false)
|
||||
{
|
||||
foreach ($this->toIterator($files) as $file) {
|
||||
foreach ($this->toIterable($files) as $file) {
|
||||
if ($recursive && is_dir($file) && !is_link($file)) {
|
||||
$this->chgrp(new \FilesystemIterator($file), $group, true);
|
||||
}
|
||||
@@ -276,6 +281,13 @@ class Filesystem
|
||||
}
|
||||
|
||||
if (true !== @rename($origin, $target)) {
|
||||
if (is_dir($origin)) {
|
||||
// See https://bugs.php.net/bug.php?id=54097 & http://php.net/manual/en/function.rename.php#113943
|
||||
$this->mirror($origin, $target, null, array('override' => $overwrite, 'delete' => $overwrite));
|
||||
$this->remove($origin);
|
||||
|
||||
return;
|
||||
}
|
||||
throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target);
|
||||
}
|
||||
}
|
||||
@@ -291,8 +303,10 @@ class Filesystem
|
||||
*/
|
||||
private function isReadable($filename)
|
||||
{
|
||||
if ('\\' === DIRECTORY_SEPARATOR && strlen($filename) > 258) {
|
||||
throw new IOException('Could not check if file is readable because path length exceeds 258 characters.', 0, null, $filename);
|
||||
$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);
|
||||
}
|
||||
|
||||
return is_readable($filename);
|
||||
@@ -332,16 +346,100 @@ class Filesystem
|
||||
}
|
||||
|
||||
if (!$ok && true !== @symlink($originDir, $targetDir)) {
|
||||
$report = error_get_last();
|
||||
if (is_array($report)) {
|
||||
if ('\\' === DIRECTORY_SEPARATOR && false !== strpos($report['message'], 'error code(1314)')) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
throw new IOException(sprintf('Failed to create symbolic link from "%s" to "%s".', $originDir, $targetDir), 0, null, $targetDir);
|
||||
$this->linkException($originDir, $targetDir, 'symbolic');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a hard link, or several hard links to a file.
|
||||
*
|
||||
* @param string $originFile The original file
|
||||
* @param string|string[] $targetFiles The target file(s)
|
||||
*
|
||||
* @throws FileNotFoundException When original file is missing or not a file
|
||||
* @throws IOException When link fails, including if link already exists
|
||||
*/
|
||||
public function hardlink($originFile, $targetFiles)
|
||||
{
|
||||
if (!$this->exists($originFile)) {
|
||||
throw new FileNotFoundException(null, 0, null, $originFile);
|
||||
}
|
||||
|
||||
if (!is_file($originFile)) {
|
||||
throw new FileNotFoundException(sprintf('Origin file "%s" is not a file', $originFile));
|
||||
}
|
||||
|
||||
foreach ($this->toIterable($targetFiles) as $targetFile) {
|
||||
if (is_file($targetFile)) {
|
||||
if (fileinode($originFile) === fileinode($targetFile)) {
|
||||
continue;
|
||||
}
|
||||
$this->remove($targetFile);
|
||||
}
|
||||
|
||||
if (true !== @link($originFile, $targetFile)) {
|
||||
$this->linkException($originFile, $targetFile, 'hard');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $origin
|
||||
* @param string $target
|
||||
* @param string $linkType Name of the link type, typically 'symbolic' or 'hard'
|
||||
*/
|
||||
private function linkException($origin, $target, $linkType)
|
||||
{
|
||||
$report = error_get_last();
|
||||
if (is_array($report)) {
|
||||
if ('\\' === DIRECTORY_SEPARATOR && false !== strpos($report['message'], '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('Failed to create %s link from "%s" to "%s".', $linkType, $origin, $target), 0, null, $target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves links in paths.
|
||||
*
|
||||
* With $canonicalize = false (default)
|
||||
* - if $path does not exist or is not a link, returns null
|
||||
* - if $path is a link, returns the next direct target of the link without considering the existence of the target
|
||||
*
|
||||
* With $canonicalize = true
|
||||
* - if $path does not exist, returns null
|
||||
* - if $path exists, returns its absolute fully resolved final version
|
||||
*
|
||||
* @param string $path A filesystem path
|
||||
* @param bool $canonicalize Whether or not to return a canonicalized path
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function readlink($path, $canonicalize = false)
|
||||
{
|
||||
if (!$canonicalize && !is_link($path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($canonicalize) {
|
||||
if (!$this->exists($path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ('\\' === DIRECTORY_SEPARATOR) {
|
||||
$path = readlink($path);
|
||||
}
|
||||
|
||||
return realpath($path);
|
||||
}
|
||||
|
||||
if ('\\' === DIRECTORY_SEPARATOR) {
|
||||
return realpath($path);
|
||||
}
|
||||
|
||||
return readlink($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an existing path, convert it to a path relative to a given starting path.
|
||||
*
|
||||
@@ -352,16 +450,48 @@ class Filesystem
|
||||
*/
|
||||
public function makePathRelative($endPath, $startPath)
|
||||
{
|
||||
if (!$this->isAbsolutePath($endPath) || !$this->isAbsolutePath($startPath)) {
|
||||
@trigger_error(sprintf('Support for passing relative paths to %s() is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
// Normalize separators on Windows
|
||||
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])) {
|
||||
return substr($path, 2);
|
||||
}
|
||||
|
||||
return $path;
|
||||
};
|
||||
|
||||
$endPath = $stripDriveLetter($endPath);
|
||||
$startPath = $stripDriveLetter($startPath);
|
||||
|
||||
// Split the paths into arrays
|
||||
$startPathArr = explode('/', trim($startPath, '/'));
|
||||
$endPathArr = explode('/', trim($endPath, '/'));
|
||||
|
||||
$normalizePathArray = function ($pathSegments, $absolute) {
|
||||
$result = array();
|
||||
|
||||
foreach ($pathSegments as $segment) {
|
||||
if ('..' === $segment && ($absolute || count($result))) {
|
||||
array_pop($result);
|
||||
} elseif ('.' !== $segment) {
|
||||
$result[] = $segment;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
};
|
||||
|
||||
$startPathArr = $normalizePathArray($startPathArr, static::isAbsolutePath($startPath));
|
||||
$endPathArr = $normalizePathArray($endPathArr, static::isAbsolutePath($endPath));
|
||||
|
||||
// Find for which directory the common path stops
|
||||
$index = 0;
|
||||
while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
|
||||
@@ -369,19 +499,14 @@ class Filesystem
|
||||
}
|
||||
|
||||
// Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels)
|
||||
if (count($startPathArr) === 1 && $startPathArr[0] === '') {
|
||||
if (1 === count($startPathArr) && '' === $startPathArr[0]) {
|
||||
$depth = 0;
|
||||
} else {
|
||||
$depth = count($startPathArr) - $index;
|
||||
}
|
||||
|
||||
// When we need to traverse from the start, and we are starting from a root path, don't add '../'
|
||||
if ('/' === $startPath[0] && 0 === $index && 0 === $depth) {
|
||||
$traverser = '';
|
||||
} else {
|
||||
// Repeated "../" for each level need to reach the common path
|
||||
$traverser = str_repeat('../', $depth);
|
||||
}
|
||||
// Repeated "../" for each level need to reach the common path
|
||||
$traverser = str_repeat('../', $depth);
|
||||
|
||||
$endPathRemainder = implode('/', array_slice($endPathArr, $index));
|
||||
|
||||
@@ -409,6 +534,7 @@ class Filesystem
|
||||
{
|
||||
$targetDir = rtrim($targetDir, '/\\');
|
||||
$originDir = rtrim($originDir, '/\\');
|
||||
$originDirLen = strlen($originDir);
|
||||
|
||||
// Iterate in destination folder to remove obsolete entries
|
||||
if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) {
|
||||
@@ -417,8 +543,9 @@ class Filesystem
|
||||
$flags = \FilesystemIterator::SKIP_DOTS;
|
||||
$deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST);
|
||||
}
|
||||
$targetDirLen = strlen($targetDir);
|
||||
foreach ($deleteIterator as $file) {
|
||||
$origin = str_replace($targetDir, $originDir, $file->getPathname());
|
||||
$origin = $originDir.substr($file->getPathname(), $targetDirLen);
|
||||
if (!$this->exists($origin)) {
|
||||
$this->remove($file);
|
||||
}
|
||||
@@ -440,7 +567,7 @@ class Filesystem
|
||||
}
|
||||
|
||||
foreach ($iterator as $file) {
|
||||
$target = str_replace($originDir, $targetDir, $file->getPathname());
|
||||
$target = $targetDir.substr($file->getPathname(), $originDirLen);
|
||||
|
||||
if ($copyOnWindows) {
|
||||
if (is_file($file)) {
|
||||
@@ -475,7 +602,7 @@ class Filesystem
|
||||
{
|
||||
return strspn($file, '/\\', 0, 1)
|
||||
|| (strlen($file) > 3 && ctype_alpha($file[0])
|
||||
&& substr($file, 1, 1) === ':'
|
||||
&& ':' === $file[1]
|
||||
&& strspn($file, '/\\', 2, 1)
|
||||
)
|
||||
|| null !== parse_url($file, PHP_URL_SCHEME)
|
||||
@@ -540,7 +667,7 @@ class Filesystem
|
||||
* @param string $filename The file to be written to
|
||||
* @param string $content The data to write into the file
|
||||
*
|
||||
* @throws IOException If the file cannot be written to.
|
||||
* @throws IOException if the file cannot be written to
|
||||
*/
|
||||
public function dumpFile($filename, $content)
|
||||
{
|
||||
@@ -548,7 +675,9 @@ class Filesystem
|
||||
|
||||
if (!is_dir($dir)) {
|
||||
$this->mkdir($dir);
|
||||
} elseif (!is_writable($dir)) {
|
||||
}
|
||||
|
||||
if (!is_writable($dir)) {
|
||||
throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir);
|
||||
}
|
||||
|
||||
@@ -560,22 +689,44 @@ class Filesystem
|
||||
throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
|
||||
}
|
||||
|
||||
@chmod($tmpFile, 0666 & ~umask());
|
||||
@chmod($tmpFile, file_exists($filename) ? fileperms($filename) : 0666 & ~umask());
|
||||
|
||||
$this->rename($tmpFile, $filename, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends content to an existing file.
|
||||
*
|
||||
* @param string $filename The file to which to append content
|
||||
* @param string $content The content to append
|
||||
*
|
||||
* @throws IOException If the file is not writable
|
||||
*/
|
||||
public function appendToFile($filename, $content)
|
||||
{
|
||||
$dir = dirname($filename);
|
||||
|
||||
if (!is_dir($dir)) {
|
||||
$this->mkdir($dir);
|
||||
}
|
||||
|
||||
if (!is_writable($dir)) {
|
||||
throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir);
|
||||
}
|
||||
|
||||
if (false === @file_put_contents($filename, $content, FILE_APPEND)) {
|
||||
throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $files
|
||||
*
|
||||
* @return \Traversable
|
||||
* @return array|\Traversable
|
||||
*/
|
||||
private function toIterator($files)
|
||||
private function toIterable($files)
|
||||
{
|
||||
if (!$files instanceof \Traversable) {
|
||||
$files = new \ArrayObject(is_array($files) ? $files : array($files));
|
||||
}
|
||||
|
||||
return $files;
|
||||
return is_array($files) || $files instanceof \Traversable ? $files : array($files);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user