Skip to content

Commit

Permalink
fix: fix logic error for file finder
Browse files Browse the repository at this point in the history
  • Loading branch information
inhere committed Apr 12, 2022
1 parent de25967 commit 9b95ed0
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 45 deletions.
118 changes: 74 additions & 44 deletions src/FileFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
use RecursiveIteratorIterator;
use RuntimeException;
use SplFileInfo;
use Toolkit\Stdlib\Str;
use Traversable;
use UnexpectedValueException;
use function array_flip;
Expand All @@ -34,6 +35,7 @@
use function fnmatch;
use function get_object_vars;
use function is_iterable;
use function is_string;
use function iterator_count;
use function str_contains;
use function stream_get_meta_data;
Expand Down Expand Up @@ -78,16 +80,14 @@ final class FileFinder implements IteratorAggregate, Countable
/** @var bool */
private bool $ignoreVcsAdded = false;

/**
* @var bool
*/
/** @var bool */
private bool $skipUnreadableDirs = true;

/** @var array */
private array $dirs = [];

/**
* File,dir name match.
* add include file,dir name match.
*
* eg: '.php' '*.php' 'test.php'
*
Expand All @@ -96,26 +96,28 @@ final class FileFinder implements IteratorAggregate, Countable
private array $names = [];

/**
* File,dir name exclude
* add exclude file,dir name patterns
*
* eg: '.php' '*.php' 'test.php'
*
* @var array
*/
private array $notNames = [];

/** @var array */
/** @var array<string> include paths pattern. */
private array $paths = [];

/** @var array */
/** @var array<string> exclude paths pattern */
private array $notPaths = [];

/**
* @var array exclude directories
*/
/** @var array<string> exclude directory names */
private array $excludes = [];

/** @var array */
/**
* path filters. each filter like: `Closure(SplFileInfo):bool`, return FALSE to exclude.
*
* @var array
*/
private array $filters = [];

/** @var array */
Expand Down Expand Up @@ -213,6 +215,8 @@ public function onlyFiles(): self
}

/**
* add include file,dir name match pattern.
*
* $finder->name('*.php')
* $finder->name('test.php')
*
Expand All @@ -222,28 +226,29 @@ public function onlyFiles(): self
*/
public function name(string $pattern): self
{
if ($pattern) {
$this->names[] = $pattern;
}

return $this;
return $this->addNames($pattern);
}

/**
* add include file,dir name match pattern.
*
* @param array|string $patterns
*
* @return FileFinder
*/
public function addNames(array|string $patterns): self
{
if ($patterns) {
$this->names = array_merge($this->names, (array)$patterns);
$patterns = is_string($patterns) ? Str::splitTrimmed($patterns) : $patterns;
// append
$this->names = array_merge($this->names, $patterns);
}

return $this;
}

/**
* add exclude file,dir name patterns
*
* @param string $pattern
*
* @return FileFinder
Expand All @@ -255,20 +260,25 @@ public function notName(string $pattern): self
}

/**
* add exclude file,dir name patterns
*
* @param array|string $patterns
*
* @return FileFinder
*/
public function notNames(array|string $patterns): self
{
if ($patterns) {
$this->notNames = array_merge($this->notNames, (array)$patterns);
$patterns = is_string($patterns) ? Str::splitTrimmed($patterns) : $patterns;
// append
$this->notNames = array_merge($this->notNames, $patterns);
}

return $this;
}

/**
* add exclude file,dir name patterns
*
* @param array|string $patterns
*
* @return FileFinder
Expand All @@ -279,6 +289,8 @@ public function addNotNames(array|string $patterns): self
}

/**
* add include paths pattern.
* eg:
* $finder->path('some/special/dir')
*
* @param string $pattern
Expand All @@ -292,33 +304,37 @@ public function path(string $pattern): self
}

/**
* add include paths pattern.
*
* @param array|string $patterns
*
* @return FileFinder
*/
public function addPaths(array|string $patterns): self
{
if ($patterns) {
$this->paths = array_merge($this->paths, (array)$patterns);
$patterns = is_string($patterns) ? Str::splitTrimmed($patterns) : $patterns;
// append
$this->paths = array_merge($this->paths, $patterns);
}

return $this;
}

/**
* add exclude paths pattern
*
* @param string $pattern
*
* @return FileFinder
*/
public function notPath(string $pattern): self
{
if ($pattern) {
$this->notPaths[] = $pattern;
}
return $this;
return $this->addNotPaths($pattern);
}

/**
* add exclude paths pattern. alias of addNotPaths()
*
* @param array|string $patterns
*
* @return FileFinder
Expand All @@ -329,30 +345,37 @@ public function notPaths(array|string $patterns): self
}

/**
* add exclude paths pattern.
* eg: $finder->addNotPaths(['vendor', 'node_modules', 'bin/'])
*
* @param array|string $patterns
*
* @return FileFinder
*/
public function addNotPaths(array|string $patterns): self
{
if ($patterns) {
$this->notPaths = array_merge($this->notPaths, (array)$patterns);
$patterns = is_string($patterns) ? Str::splitTrimmed($patterns) : $patterns;
// append
$this->notPaths = array_merge($this->notPaths, $patterns);
}

return $this;
}

/**
* @param $dirs
* exclude directory names
*
* @param array|string $dirNames
*
* @return FileFinder
*/
public function exclude($dirs): self
public function exclude(array|string $dirNames): self
{
if ($dirs) {
$this->excludes = array_merge($this->excludes, (array)$dirs);
if ($dirNames) {
$dirNames = is_string($dirNames) ? Str::splitTrimmed($dirNames) : $dirNames;
// append
$this->excludes = array_merge($this->excludes, $dirNames);
}

return $this;
}

Expand Down Expand Up @@ -429,14 +452,13 @@ public function followLinks(mixed $followLinks = true): self
}

/**
* @param Closure $closure
* @param Closure(SplFileInfo): bool $closure
*
* @return FileFinder
*/
public function filter(Closure $closure): self
{
$this->filters[] = $closure;

return $this;
}

Expand All @@ -460,9 +482,10 @@ public function in(array|string $dirs): self
public function inDir(array|string $dirs): self
{
if ($dirs) {
$this->dirs = array_merge($this->dirs, (array)$dirs);
$dirs = is_string($dirs) ? Str::splitTrimmed($dirs) : $dirs;
// append
$this->dirs = array_merge($this->dirs, $dirs);
}

return $this;
}

Expand Down Expand Up @@ -585,7 +608,7 @@ private function findInDirectory(string $dir): Iterator
$flags |= RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
}

$iterator = new class($dir, $flags) extends RecursiveDirectoryIterator {
$iterator = new class($dir, $flags, $this->skipUnreadableDirs) extends RecursiveDirectoryIterator {
private string $rootPath;
private string $subPath = '';
private bool|null $rewindable = null;
Expand All @@ -610,8 +633,9 @@ public function __construct(string $path, int $flags, bool $skipUnreadableDirs =

public function current(): SplFileInfo
{
// vdump($this->getPathname(), $this);
if (null === $subPathname = $this->subPath) {
$subPathname = $this->subPath = (string)$this->getSubPath();
$subPathname = $this->subPath = $this->getSubPath();
}

if ('' !== $subPathname) {
Expand All @@ -620,8 +644,9 @@ public function current(): SplFileInfo

$subPathname .= $this->getFilename();

// $fileInfo = new \SplFileInfo($this->getPathname());
$fileInfo = new SplFileInfo($this->rootPath . $this->directorySep . $subPathname);
$fileInfo = new SplFileInfo($this->getPathname());
// $fileInfo = new SplFileInfo($this->rootPath . $this->directorySep . $subPathname);
// vdump($this->rootPath, $subPathname, $fileInfo);
// add props
$fileInfo->relativePath = $this->subPath;
$fileInfo->relativePathname = $subPathname;
Expand All @@ -634,7 +659,7 @@ public function getChildren(): RecursiveDirectoryIterator
try {
$children = parent::getChildren();
if ($children instanceof self) {
$children->rootPath = $this->rootPath;
$children->rootPath = $this->rootPath;
$children->rewindable = &$this->rewindable;
$children->skipUnreadableDirs = $this->skipUnreadableDirs;
}
Expand Down Expand Up @@ -680,6 +705,7 @@ public function isRewindable(): ?bool
// exclude directories
if ($this->excludes) {
$iterator = new class($iterator, $this->excludes) extends FilterIterator implements RecursiveIterator {
/** @var array<string, int> */
private array $excludes;

private RecursiveIterator $iterator;
Expand Down Expand Up @@ -734,6 +760,7 @@ public function __construct(Iterator $iterator, int $mode)

public function accept(): bool
{
/** @var SplFileInfo $info */
$info = $this->current();
if (FileFinder::ONLY_DIR === $this->mode && $info->isFile()) {
return false;
Expand Down Expand Up @@ -796,6 +823,7 @@ public function __construct(Iterator $iterator, array $filters)

public function accept(): bool
{
/** @var SplFileInfo $fileInfo */
$fileInfo = $this->current();
foreach ($this->filters as $filter) {
if (false === $filter($fileInfo)) {
Expand All @@ -810,8 +838,9 @@ public function accept(): bool

if ($this->paths || $this->notPaths) {
$iterator = new class($iterator, $this->paths, $this->notPaths) extends FilterIterator {
/** @var array<string> */
private array $paths;

/** @var array<string> */
private array $notPaths;

public function __construct(Iterator $iterator, array $paths, array $notPaths)
Expand All @@ -823,7 +852,8 @@ public function __construct(Iterator $iterator, array $paths, array $notPaths)

public function accept(): bool
{
$pathname = $this->current()->relativePathname;
/** @var string $pathname {@see SplFileInfo::getPathname()} */
$pathname = $this->current()->getPathname();
if ('\\' === DIRECTORY_SEPARATOR) {
$pathname = str_replace('\\', '/', $pathname);
}
Expand Down
13 changes: 12 additions & 1 deletion src/Traits/FileSystemFuncTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
use function str_replace;
use function stream_get_meta_data;
use function strlen;
use function strpos;
use const DIRECTORY_SEPARATOR;

/**
Expand Down Expand Up @@ -228,6 +227,18 @@ public static function chown(Traversable|array|string $files, string $user, bool
}
}

/**
* clear invalid sep and will parse ~ as user home dir.
*
* @param string $path
*
* @return string
*/
public static function expandPath(string $path): string
{
$path = realpath($path);
}

/**
* clear invalid sep and will parse ~ as user home dir.
*
Expand Down

0 comments on commit 9b95ed0

Please sign in to comment.