upgraded dependencies

This commit is contained in:
RafficMohammed
2023-01-08 01:59:16 +05:30
parent 51056e3aad
commit f9ae387337
6895 changed files with 133617 additions and 178680 deletions

View File

@@ -1,6 +1,19 @@
CHANGELOG
=========
5.4.0
-----
* Deprecate `Comparator::setTarget()` and `Comparator::setOperator()`
* Add a constructor to `Comparator` that allows setting target and operator
* Finder's iterator has now `Symfony\Component\Finder\SplFileInfo` inner type specified
* Add recursive .gitignore files support
5.0.0
-----
* added `$useNaturalSort` argument to `Finder::sortByName()`
4.3.0
-----

View File

@@ -12,8 +12,6 @@
namespace Symfony\Component\Finder\Comparator;
/**
* Comparator.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Comparator
@@ -21,30 +19,44 @@ class Comparator
private $target;
private $operator = '==';
public function __construct(string $target = null, string $operator = '==')
{
if (null === $target) {
trigger_deprecation('symfony/finder', '5.4', 'Constructing a "%s" without setting "$target" is deprecated.', __CLASS__);
}
$this->target = $target;
$this->doSetOperator($operator);
}
/**
* Gets the target value.
*
* @return string The target value
* @return string
*/
public function getTarget()
{
if (null === $this->target) {
trigger_deprecation('symfony/finder', '5.4', 'Calling "%s" without initializing the target is deprecated.', __METHOD__);
}
return $this->target;
}
/**
* Sets the target value.
*
* @param string $target The target value
* @deprecated set the target via the constructor instead
*/
public function setTarget($target)
public function setTarget(string $target)
{
trigger_deprecation('symfony/finder', '5.4', '"%s" is deprecated. Set the target via the constructor instead.', __METHOD__);
$this->target = $target;
}
/**
* Gets the comparison operator.
*
* @return string The operator
* @return string
*/
public function getOperator()
{
@@ -54,21 +66,15 @@ class Comparator
/**
* Sets the comparison operator.
*
* @param string $operator A valid operator
*
* @throws \InvalidArgumentException
*
* @deprecated set the operator via the constructor instead
*/
public function setOperator($operator)
public function setOperator(string $operator)
{
if (!$operator) {
$operator = '==';
}
trigger_deprecation('symfony/finder', '5.4', '"%s" is deprecated. Set the operator via the constructor instead.', __METHOD__);
if (!\in_array($operator, ['>', '<', '>=', '<=', '==', '!='])) {
throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
}
$this->operator = $operator;
$this->doSetOperator('' === $operator ? '==' : $operator);
}
/**
@@ -80,6 +86,10 @@ class Comparator
*/
public function test($test)
{
if (null === $this->target) {
trigger_deprecation('symfony/finder', '5.4', 'Calling "%s" without initializing the target is deprecated.', __METHOD__);
}
switch ($this->operator) {
case '>':
return $test > $this->target;
@@ -95,4 +105,13 @@ class Comparator
return $test == $this->target;
}
private function doSetOperator(string $operator): void
{
if (!\in_array($operator, ['>', '<', '>=', '<=', '==', '!='])) {
throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
}
$this->operator = $operator;
}
}

View File

@@ -45,7 +45,6 @@ class DateComparator extends Comparator
$operator = '<';
}
$this->setOperator($operator);
$this->setTarget($target);
parent::__construct($target, $operator);
}
}

View File

@@ -73,7 +73,6 @@ class NumberComparator extends Comparator
}
}
$this->setTarget($target);
$this->setOperator($matches[1] ?? '==');
parent::__construct($target, $matches[1] ?: '==');
}
}

View File

@@ -36,6 +36,8 @@ use Symfony\Component\Finder\Iterator\SortableIterator;
* $finder = Finder::create()->files()->name('*.php')->in(__DIR__);
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @implements \IteratorAggregate<string, SplFileInfo>
*/
class Finder implements \IteratorAggregate, \Countable
{
@@ -337,13 +339,11 @@ class Finder implements \IteratorAggregate, \Countable
*
* This option is enabled by default.
*
* @param bool $ignoreDotFiles Whether to exclude "hidden" files or not
*
* @return $this
*
* @see ExcludeDirectoryFilterIterator
*/
public function ignoreDotFiles($ignoreDotFiles)
public function ignoreDotFiles(bool $ignoreDotFiles)
{
if ($ignoreDotFiles) {
$this->ignore |= static::IGNORE_DOT_FILES;
@@ -359,13 +359,11 @@ class Finder implements \IteratorAggregate, \Countable
*
* This option is enabled by default.
*
* @param bool $ignoreVCS Whether to exclude VCS files or not
*
* @return $this
*
* @see ExcludeDirectoryFilterIterator
*/
public function ignoreVCS($ignoreVCS)
public function ignoreVCS(bool $ignoreVCS)
{
if ($ignoreVCS) {
$this->ignore |= static::IGNORE_VCS_FILES;
@@ -433,19 +431,12 @@ class Finder implements \IteratorAggregate, \Countable
*
* This can be slow as all the matching files and directories must be retrieved for comparison.
*
* @param bool $useNaturalSort Whether to use natural sort or not, disabled by default
*
* @return $this
*
* @see SortableIterator
*/
public function sortByName(/* bool $useNaturalSort = false */)
public function sortByName(bool $useNaturalSort = false)
{
if (\func_num_args() < 1 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface && !$this instanceof \Mockery\MockInterface) {
@trigger_error(sprintf('The "%s()" method will have a new "bool $useNaturalSort = false" argument in version 5.0, not defining it is deprecated since Symfony 4.2.', __METHOD__), \E_USER_DEPRECATED);
}
$useNaturalSort = 0 < \func_num_args() && func_get_arg(0);
$this->sort = $useNaturalSort ? Iterator\SortableIterator::SORT_BY_NAME_NATURAL : Iterator\SortableIterator::SORT_BY_NAME;
return $this;
@@ -569,13 +560,11 @@ class Finder implements \IteratorAggregate, \Countable
*
* By default, scanning unreadable directories content throws an AccessDeniedException.
*
* @param bool $ignore
*
* @return $this
*/
public function ignoreUnreadableDirs($ignore = true)
public function ignoreUnreadableDirs(bool $ignore = true)
{
$this->ignoreUnreadableDirs = (bool) $ignore;
$this->ignoreUnreadableDirs = $ignore;
return $this;
}
@@ -595,16 +584,16 @@ class Finder implements \IteratorAggregate, \Countable
foreach ((array) $dirs as $dir) {
if (is_dir($dir)) {
$resolvedDirs[] = $this->normalizeDir($dir);
$resolvedDirs[] = [$this->normalizeDir($dir)];
} elseif ($glob = glob($dir, (\defined('GLOB_BRACE') ? \GLOB_BRACE : 0) | \GLOB_ONLYDIR | \GLOB_NOSORT)) {
sort($glob);
$resolvedDirs = array_merge($resolvedDirs, array_map([$this, 'normalizeDir'], $glob));
$resolvedDirs[] = array_map([$this, 'normalizeDir'], $glob);
} else {
throw new DirectoryNotFoundException(sprintf('The "%s" directory does not exist.', $dir));
}
}
$this->dirs = array_merge($this->dirs, $resolvedDirs);
$this->dirs = array_merge($this->dirs, ...$resolvedDirs);
return $this;
}
@@ -614,7 +603,7 @@ class Finder implements \IteratorAggregate, \Countable
*
* This method implements the IteratorAggregate interface.
*
* @return \Iterator|SplFileInfo[] An iterator
* @return \Iterator<string, SplFileInfo>
*
* @throws \LogicException if the in() method has not been called
*/
@@ -658,13 +647,11 @@ class Finder implements \IteratorAggregate, \Countable
*
* The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array.
*
* @param iterable $iterator
*
* @return $this
*
* @throws \InvalidArgumentException when the given argument is not iterable
*/
public function append($iterator)
public function append(iterable $iterator)
{
if ($iterator instanceof \IteratorAggregate) {
$this->iterators[] = $iterator->getIterator();
@@ -722,14 +709,6 @@ class Finder implements \IteratorAggregate, \Countable
$notPaths[] = '#(^|/)\..+(/|$)#';
}
if (static::IGNORE_VCS_IGNORED_FILES === (static::IGNORE_VCS_IGNORED_FILES & $this->ignore)) {
$gitignoreFilePath = sprintf('%s/.gitignore', $dir);
if (!is_readable($gitignoreFilePath)) {
throw new \RuntimeException(sprintf('The "ignoreVCSIgnored" option cannot be used by the Finder as the "%s" file is not readable.', $gitignoreFilePath));
}
$notPaths = array_merge($notPaths, [Gitignore::toRegex(file_get_contents($gitignoreFilePath))]);
}
$minDepth = 0;
$maxDepth = \PHP_INT_MAX;
@@ -798,6 +777,10 @@ class Finder implements \IteratorAggregate, \Countable
$iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $notPaths);
}
if (static::IGNORE_VCS_IGNORED_FILES === (static::IGNORE_VCS_IGNORED_FILES & $this->ignore)) {
$iterator = new Iterator\VcsIgnoredFilterIterator($iterator, $dir);
}
return $iterator;
}

View File

@@ -25,12 +25,22 @@ class Gitignore
* Format specification: https://git-scm.com/docs/gitignore#_pattern_format
*/
public static function toRegex(string $gitignoreFileContent): string
{
return self::buildRegex($gitignoreFileContent, false);
}
public static function toRegexMatchingNegatedPatterns(string $gitignoreFileContent): string
{
return self::buildRegex($gitignoreFileContent, true);
}
private static function buildRegex(string $gitignoreFileContent, bool $inverted): string
{
$gitignoreFileContent = preg_replace('~(?<!\\\\)#[^\n\r]*~', '', $gitignoreFileContent);
$gitignoreLines = preg_split('~\r\n?|\n~', $gitignoreFileContent);
$res = self::lineToRegex('');
foreach ($gitignoreLines as $i => $line) {
foreach ($gitignoreLines as $line) {
$line = preg_replace('~(?<!\\\\)[ \t]+$~', '', $line);
if ('!' === substr($line, 0, 1)) {
@@ -41,7 +51,7 @@ class Gitignore
}
if ('' !== $line) {
if ($isNegative) {
if ($isNegative xor $inverted) {
$res = '(?!'.self::lineToRegex($line).'$)'.$res;
} else {
$res = '(?:'.$res.'|'.self::lineToRegex($line).')';

View File

@@ -38,14 +38,9 @@ class Glob
/**
* Returns a regexp which is the equivalent of the glob pattern.
*
* @param string $glob The glob pattern
* @param bool $strictLeadingDot
* @param bool $strictWildcardSlash
* @param string $delimiter Optional delimiter
*
* @return string regex The regexp
* @return string
*/
public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true, $delimiter = '#')
public static function toRegex(string $glob, bool $strictLeadingDot = true, bool $strictWildcardSlash = true, string $delimiter = '#')
{
$firstByte = true;
$escaping = false;

View File

@@ -18,14 +18,16 @@ namespace Symfony\Component\Finder\Iterator;
* to remove files.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @extends \FilterIterator<string, \SplFileInfo>
*/
class CustomFilterIterator extends \FilterIterator
{
private $filters = [];
/**
* @param \Iterator $iterator The Iterator to filter
* @param callable[] $filters An array of PHP callbacks
* @param \Iterator<string, \SplFileInfo> $iterator The Iterator to filter
* @param callable[] $filters An array of PHP callbacks
*
* @throws \InvalidArgumentException
*/
@@ -44,7 +46,7 @@ class CustomFilterIterator extends \FilterIterator
/**
* Filters the iterator values.
*
* @return bool true if the value should be kept, false otherwise
* @return bool
*/
#[\ReturnTypeWillChange]
public function accept()

View File

@@ -17,14 +17,16 @@ use Symfony\Component\Finder\Comparator\DateComparator;
* DateRangeFilterIterator filters out files that are not in the given date range (last modified dates).
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @extends \FilterIterator<string, \SplFileInfo>
*/
class DateRangeFilterIterator extends \FilterIterator
{
private $comparators = [];
/**
* @param \Iterator $iterator The Iterator to filter
* @param DateComparator[] $comparators An array of DateComparator instances
* @param \Iterator<string, \SplFileInfo> $iterator
* @param DateComparator[] $comparators
*/
public function __construct(\Iterator $iterator, array $comparators)
{
@@ -36,7 +38,7 @@ class DateRangeFilterIterator extends \FilterIterator
/**
* Filters the iterator values.
*
* @return bool true if the value should be kept, false otherwise
* @return bool
*/
#[\ReturnTypeWillChange]
public function accept()

View File

@@ -15,15 +15,20 @@ namespace Symfony\Component\Finder\Iterator;
* DepthRangeFilterIterator limits the directory depth.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @template-covariant TKey
* @template-covariant TValue
*
* @extends \FilterIterator<TKey, TValue>
*/
class DepthRangeFilterIterator extends \FilterIterator
{
private $minDepth = 0;
/**
* @param \RecursiveIteratorIterator $iterator The Iterator to filter
* @param int $minDepth The min depth
* @param int $maxDepth The max depth
* @param \RecursiveIteratorIterator<\RecursiveIterator<TKey, TValue>> $iterator The Iterator to filter
* @param int $minDepth The min depth
* @param int $maxDepth The max depth
*/
public function __construct(\RecursiveIteratorIterator $iterator, int $minDepth = 0, int $maxDepth = \PHP_INT_MAX)
{
@@ -36,7 +41,7 @@ class DepthRangeFilterIterator extends \FilterIterator
/**
* Filters the iterator values.
*
* @return bool true if the value should be kept, false otherwise
* @return bool
*/
#[\ReturnTypeWillChange]
public function accept()

View File

@@ -15,6 +15,9 @@ namespace Symfony\Component\Finder\Iterator;
* ExcludeDirectoryFilterIterator filters out directories.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @extends \FilterIterator<string, \SplFileInfo>
* @implements \RecursiveIterator<string, \SplFileInfo>
*/
class ExcludeDirectoryFilterIterator extends \FilterIterator implements \RecursiveIterator
{
@@ -50,7 +53,7 @@ class ExcludeDirectoryFilterIterator extends \FilterIterator implements \Recursi
/**
* Filters the iterator values.
*
* @return bool True if the value should be kept, false otherwise
* @return bool
*/
#[\ReturnTypeWillChange]
public function accept()

View File

@@ -15,6 +15,8 @@ namespace Symfony\Component\Finder\Iterator;
* FileTypeFilterIterator only keeps files, directories, or both.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @extends \FilterIterator<string, \SplFileInfo>
*/
class FileTypeFilterIterator extends \FilterIterator
{
@@ -37,7 +39,7 @@ class FileTypeFilterIterator extends \FilterIterator
/**
* Filters the iterator values.
*
* @return bool true if the value should be kept, false otherwise
* @return bool
*/
#[\ReturnTypeWillChange]
public function accept()

View File

@@ -16,13 +16,15 @@ namespace Symfony\Component\Finder\Iterator;
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Włodzimierz Gajda <gajdaw@gajdaw.pl>
*
* @extends MultiplePcreFilterIterator<string, \SplFileInfo>
*/
class FilecontentFilterIterator extends MultiplePcreFilterIterator
{
/**
* Filters the iterator values.
*
* @return bool true if the value should be kept, false otherwise
* @return bool
*/
#[\ReturnTypeWillChange]
public function accept()
@@ -50,9 +52,9 @@ class FilecontentFilterIterator extends MultiplePcreFilterIterator
*
* @param string $str Pattern: string or regexp
*
* @return string regexp corresponding to a given string or regexp
* @return string
*/
protected function toRegex($str)
protected function toRegex(string $str)
{
return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
}

View File

@@ -17,13 +17,15 @@ use Symfony\Component\Finder\Glob;
* FilenameFilterIterator filters files by patterns (a regexp, a glob, or a string).
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @extends MultiplePcreFilterIterator<string, \SplFileInfo>
*/
class FilenameFilterIterator extends MultiplePcreFilterIterator
{
/**
* Filters the iterator values.
*
* @return bool true if the value should be kept, false otherwise
* @return bool
*/
#[\ReturnTypeWillChange]
public function accept()
@@ -39,9 +41,9 @@ class FilenameFilterIterator extends MultiplePcreFilterIterator
*
* @param string $str Pattern: glob or regexp
*
* @return string regexp corresponding to a given glob or regexp
* @return string
*/
protected function toRegex($str)
protected function toRegex(string $str)
{
return $this->isRegex($str) ? $str : Glob::toRegex($str);
}

View File

@@ -15,6 +15,11 @@ namespace Symfony\Component\Finder\Iterator;
* MultiplePcreFilterIterator filters files using patterns (regexps, globs or strings).
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @template-covariant TKey
* @template-covariant TValue
*
* @extends \FilterIterator<TKey, TValue>
*/
abstract class MultiplePcreFilterIterator extends \FilterIterator
{
@@ -23,8 +28,8 @@ abstract class MultiplePcreFilterIterator extends \FilterIterator
/**
* @param \Iterator $iterator The Iterator to filter
* @param array $matchPatterns An array of patterns that need to match
* @param array $noMatchPatterns An array of patterns that need to not match
* @param string[] $matchPatterns An array of patterns that need to match
* @param string[] $noMatchPatterns An array of patterns that need to not match
*/
public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns)
{
@@ -46,11 +51,9 @@ abstract class MultiplePcreFilterIterator extends \FilterIterator
* Such case can be handled by child classes before calling the method if they want to
* apply a different behavior.
*
* @param string $string The string to be matched against filters
*
* @return bool
*/
protected function isAccepted($string)
protected function isAccepted(string $string)
{
// should at least not match one rule to exclude
foreach ($this->noMatchRegexps as $regex) {
@@ -77,11 +80,9 @@ abstract class MultiplePcreFilterIterator extends \FilterIterator
/**
* Checks whether the string is a regex.
*
* @param string $str
*
* @return bool Whether the given string is a regex
* @return bool
*/
protected function isRegex($str)
protected function isRegex(string $str)
{
$availableModifiers = 'imsxuADU';
@@ -110,9 +111,7 @@ abstract class MultiplePcreFilterIterator extends \FilterIterator
/**
* Converts string into regexp.
*
* @param string $str Pattern
*
* @return string regexp corresponding to a given string
* @return string
*/
abstract protected function toRegex($str);
abstract protected function toRegex(string $str);
}

View File

@@ -16,13 +16,15 @@ namespace Symfony\Component\Finder\Iterator;
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Włodzimierz Gajda <gajdaw@gajdaw.pl>
*
* @extends MultiplePcreFilterIterator<string, \SplFileInfo>
*/
class PathFilterIterator extends MultiplePcreFilterIterator
{
/**
* Filters the iterator values.
*
* @return bool true if the value should be kept, false otherwise
* @return bool
*/
#[\ReturnTypeWillChange]
public function accept()
@@ -48,9 +50,9 @@ class PathFilterIterator extends MultiplePcreFilterIterator
*
* @param string $str Pattern: regexp or dirname
*
* @return string regexp corresponding to a given string or regexp
* @return string
*/
protected function toRegex($str)
protected function toRegex(string $str)
{
return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
}

View File

@@ -56,7 +56,7 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
/**
* Return an instance of SplFileInfo with support for relative paths.
*
* @return SplFileInfo File information
* @return SplFileInfo
*/
#[\ReturnTypeWillChange]
public function current()
@@ -79,7 +79,31 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
}
/**
* @return \RecursiveIterator
* @param bool $allowLinks
*
* @return bool
*/
#[\ReturnTypeWillChange]
public function hasChildren($allowLinks = false)
{
$hasChildren = parent::hasChildren($allowLinks);
if (!$hasChildren || !$this->ignoreUnreadableDirs) {
return $hasChildren;
}
try {
parent::getChildren();
return true;
} catch (\UnexpectedValueException $e) {
// If directory is unreadable and finder is set to ignore it, skip children
return false;
}
}
/**
* @return \RecursiveDirectoryIterator
*
* @throws AccessDeniedException
*/
@@ -100,12 +124,7 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
return $children;
} catch (\UnexpectedValueException $e) {
if ($this->ignoreUnreadableDirs) {
// If directory is unreadable and finder is set to ignore it, a fake empty content is returned.
return new \RecursiveArrayIterator([]);
} else {
throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
}
throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
}
}
@@ -127,7 +146,7 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
/**
* Checks if the stream is rewindable.
*
* @return bool true when the stream is rewindable, false otherwise
* @return bool
*/
public function isRewindable()
{

View File

@@ -17,14 +17,16 @@ use Symfony\Component\Finder\Comparator\NumberComparator;
* SizeRangeFilterIterator filters out files that are not in the given size range.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @extends \FilterIterator<string, \SplFileInfo>
*/
class SizeRangeFilterIterator extends \FilterIterator
{
private $comparators = [];
/**
* @param \Iterator $iterator The Iterator to filter
* @param NumberComparator[] $comparators An array of NumberComparator instances
* @param \Iterator<string, \SplFileInfo> $iterator
* @param NumberComparator[] $comparators
*/
public function __construct(\Iterator $iterator, array $comparators)
{
@@ -36,7 +38,7 @@ class SizeRangeFilterIterator extends \FilterIterator
/**
* Filters the iterator values.
*
* @return bool true if the value should be kept, false otherwise
* @return bool
*/
#[\ReturnTypeWillChange]
public function accept()

View File

@@ -15,6 +15,8 @@ namespace Symfony\Component\Finder\Iterator;
* SortableIterator applies a sort on a given Iterator.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @implements \IteratorAggregate<string, \SplFileInfo>
*/
class SortableIterator implements \IteratorAggregate
{
@@ -30,7 +32,8 @@ class SortableIterator implements \IteratorAggregate
private $sort;
/**
* @param int|callable $sort The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback)
* @param \Traversable<string, \SplFileInfo> $iterator
* @param int|callable $sort The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback)
*
* @throws \InvalidArgumentException
*/
@@ -40,15 +43,15 @@ class SortableIterator implements \IteratorAggregate
$order = $reverseOrder ? -1 : 1;
if (self::SORT_BY_NAME === $sort) {
$this->sort = static function ($a, $b) use ($order) {
$this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) {
return $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname());
};
} elseif (self::SORT_BY_NAME_NATURAL === $sort) {
$this->sort = static function ($a, $b) use ($order) {
$this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) {
return $order * strnatcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname());
};
} elseif (self::SORT_BY_TYPE === $sort) {
$this->sort = static function ($a, $b) use ($order) {
$this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) {
if ($a->isDir() && $b->isFile()) {
return -$order;
} elseif ($a->isFile() && $b->isDir()) {
@@ -58,28 +61,28 @@ class SortableIterator implements \IteratorAggregate
return $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname());
};
} elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
$this->sort = static function ($a, $b) use ($order) {
$this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) {
return $order * ($a->getATime() - $b->getATime());
};
} elseif (self::SORT_BY_CHANGED_TIME === $sort) {
$this->sort = static function ($a, $b) use ($order) {
$this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) {
return $order * ($a->getCTime() - $b->getCTime());
};
} elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
$this->sort = static function ($a, $b) use ($order) {
$this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) {
return $order * ($a->getMTime() - $b->getMTime());
};
} elseif (self::SORT_BY_NONE === $sort) {
$this->sort = $order;
} elseif (\is_callable($sort)) {
$this->sort = $reverseOrder ? static function ($a, $b) use ($sort) { return -$sort($a, $b); } : $sort;
$this->sort = $reverseOrder ? static function (\SplFileInfo $a, \SplFileInfo $b) use ($sort) { return -$sort($a, $b); } : $sort;
} else {
throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.');
}
}
/**
* @return \Traversable
* @return \Traversable<string, \SplFileInfo>
*/
#[\ReturnTypeWillChange]
public function getIterator()

View File

@@ -0,0 +1,151 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Finder\Iterator;
use Symfony\Component\Finder\Gitignore;
final class VcsIgnoredFilterIterator extends \FilterIterator
{
/**
* @var string
*/
private $baseDir;
/**
* @var array<string, array{0: string, 1: string}|null>
*/
private $gitignoreFilesCache = [];
/**
* @var array<string, bool>
*/
private $ignoredPathsCache = [];
public function __construct(\Iterator $iterator, string $baseDir)
{
$this->baseDir = $this->normalizePath($baseDir);
parent::__construct($iterator);
}
public function accept(): bool
{
$file = $this->current();
$fileRealPath = $this->normalizePath($file->getRealPath());
return !$this->isIgnored($fileRealPath);
}
private function isIgnored(string $fileRealPath): bool
{
if (is_dir($fileRealPath) && !str_ends_with($fileRealPath, '/')) {
$fileRealPath .= '/';
}
if (isset($this->ignoredPathsCache[$fileRealPath])) {
return $this->ignoredPathsCache[$fileRealPath];
}
$ignored = false;
foreach ($this->parentsDirectoryDownward($fileRealPath) as $parentDirectory) {
if ($this->isIgnored($parentDirectory)) {
// rules in ignored directories are ignored, no need to check further.
break;
}
$fileRelativePath = substr($fileRealPath, \strlen($parentDirectory) + 1);
if (null === $regexps = $this->readGitignoreFile("{$parentDirectory}/.gitignore")) {
continue;
}
[$exclusionRegex, $inclusionRegex] = $regexps;
if (preg_match($exclusionRegex, $fileRelativePath)) {
$ignored = true;
continue;
}
if (preg_match($inclusionRegex, $fileRelativePath)) {
$ignored = false;
}
}
return $this->ignoredPathsCache[$fileRealPath] = $ignored;
}
/**
* @return list<string>
*/
private function parentsDirectoryDownward(string $fileRealPath): array
{
$parentDirectories = [];
$parentDirectory = $fileRealPath;
while (true) {
$newParentDirectory = \dirname($parentDirectory);
// dirname('/') = '/'
if ($newParentDirectory === $parentDirectory) {
break;
}
$parentDirectory = $newParentDirectory;
if (0 !== strpos($parentDirectory, $this->baseDir)) {
break;
}
$parentDirectories[] = $parentDirectory;
}
return array_reverse($parentDirectories);
}
/**
* @return array{0: string, 1: string}|null
*/
private function readGitignoreFile(string $path): ?array
{
if (\array_key_exists($path, $this->gitignoreFilesCache)) {
return $this->gitignoreFilesCache[$path];
}
if (!file_exists($path)) {
return $this->gitignoreFilesCache[$path] = null;
}
if (!is_file($path) || !is_readable($path)) {
throw new \RuntimeException("The \"ignoreVCSIgnored\" option cannot be used by the Finder as the \"{$path}\" file is not readable.");
}
$gitignoreFileContent = file_get_contents($path);
return $this->gitignoreFilesCache[$path] = [
Gitignore::toRegex($gitignoreFileContent),
Gitignore::toRegexMatchingNegatedPatterns($gitignoreFileContent),
];
}
private function normalizePath(string $path): string
{
if ('\\' === \DIRECTORY_SEPARATOR) {
return str_replace('\\', '/', $path);
}
return $path;
}
}

View File

@@ -38,7 +38,7 @@ class SplFileInfo extends \SplFileInfo
*
* This path does not contain the file name.
*
* @return string the relative path
* @return string
*/
public function getRelativePath()
{
@@ -50,7 +50,7 @@ class SplFileInfo extends \SplFileInfo
*
* This path contains the file name.
*
* @return string the relative path name
* @return string
*/
public function getRelativePathname()
{
@@ -67,15 +67,18 @@ class SplFileInfo extends \SplFileInfo
/**
* Returns the contents of the file.
*
* @return string the contents of the file
* @return string
*
* @throws \RuntimeException
*/
public function getContents()
{
set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
$content = file_get_contents($this->getPathname());
restore_error_handler();
try {
$content = file_get_contents($this->getPathname());
} finally {
restore_error_handler();
}
if (false === $content) {
throw new \RuntimeException($error);
}

View File

@@ -16,7 +16,8 @@
}
],
"require": {
"php": ">=7.1.3",
"php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1|^3",
"symfony/polyfill-php80": "^1.16"
},
"autoload": {