Skip to content

[Finder] Exclude relative to content root if prefixed / #54752

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: 5.4
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class ExcludeDirectoryFilterIterator extends \FilterIterator implements \Recursi
private $isRecursive;
private $excludedDirs = [];
private $excludedPattern;
private $excludedPatternAbsolute;

/**
* @param \Iterator $iterator The Iterator to filter
Expand All @@ -36,9 +37,16 @@ public function __construct(\Iterator $iterator, array $directories)
$this->iterator = $iterator;
$this->isRecursive = $iterator instanceof \RecursiveIterator;
$patterns = [];
$patternsAbsolute = [];
foreach ($directories as $directory) {
$directory = rtrim($directory, '/');
if (!$this->isRecursive || str_contains($directory, '/')) {
$slashPos = strpos($directory, '/');
if (false !== $slashPos && \strlen($directory) - 1 !== $slashPos) {
if (0 === $slashPos) {
$directory = substr($directory, 1);
}
$patternsAbsolute[] = preg_quote($directory, '#');
} elseif (!$this->isRecursive || str_contains($directory, '/')) {
$patterns[] = preg_quote($directory, '#');
} else {
$this->excludedDirs[$directory] = true;
Expand All @@ -48,6 +56,10 @@ public function __construct(\Iterator $iterator, array $directories)
$this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#';
}

if ($patternsAbsolute) {
$this->excludedPatternAbsolute = '#^('.implode('|', $patternsAbsolute).')$#';
}

parent::__construct($iterator);
}

Expand All @@ -63,11 +75,17 @@ public function accept()
return false;
}

if ($this->excludedPattern) {
if ($this->excludedPattern || $this->excludedPatternAbsolute) {
$path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
$path = str_replace('\\', '/', $path);
}

return !preg_match($this->excludedPattern, $path);
if ($this->excludedPattern && preg_match($this->excludedPattern, $path)) {
return false;
}

if ($this->excludedPatternAbsolute && preg_match($this->excludedPatternAbsolute, $path)) {
return false;
}

return true;
Expand Down
81 changes: 74 additions & 7 deletions src/Symfony/Component/Finder/Tests/FinderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ public function testDirectories()
{
$finder = $this->buildFinder();
$this->assertSame($finder, $finder->directories());
$this->assertIterator($this->toAbsolute(['foo', 'qux', 'toto']), $finder->in(self::$tmpDir)->getIterator());
$this->assertIterator($this->toAbsolute(['foo', 'qux', 'toto', 'toto/foo']), $finder->in(self::$tmpDir)->getIterator());

$finder = $this->buildFinder();
$finder->directories();
$finder->files();
$finder->directories();
$this->assertIterator($this->toAbsolute(['foo', 'qux', 'toto']), $finder->in(self::$tmpDir)->getIterator());
$this->assertIterator($this->toAbsolute(['foo', 'qux', 'toto', 'toto/foo']), $finder->in(self::$tmpDir)->getIterator());
}

public function testFiles()
Expand Down Expand Up @@ -162,7 +162,8 @@ public function testDepth()
$this->assertIterator($this->toAbsolute([
'foo/bar.tmp',
'qux/baz_100_1.py',
'qux/baz_1_2.py',
'qux/baz_1_2.py',
'toto/foo',
]), $finder->in(self::$tmpDir)->getIterator());

$finder = $this->buildFinder();
Expand All @@ -178,6 +179,7 @@ public function testDepthWithArrayParam()
'foo/bar.tmp',
'qux/baz_100_1.py',
'qux/baz_1_2.py',
'toto/foo',
]), $finder->in(self::$tmpDir)->getIterator());
}

Expand Down Expand Up @@ -237,6 +239,7 @@ public function testNotName()
'foo/bar.tmp',
'test.py',
'toto',
'toto/foo',
'foo bar',
'qux',
'qux/baz_100_1.py',
Expand All @@ -250,6 +253,7 @@ public function testNotName()
'foo',
'foo/bar.tmp',
'toto',
'toto/foo',
'foo bar',
'qux',
]), $finder->in(self::$tmpDir)->getIterator());
Expand All @@ -276,6 +280,7 @@ public function testNotNameWithArrayParam()
'foo',
'foo/bar.tmp',
'toto',
'toto/foo',
'foo bar',
'qux',
]), $finder->in(self::$tmpDir)->getIterator());
Expand Down Expand Up @@ -340,7 +345,47 @@ public function testExclude()
'qux_10_2.php',
'qux_12_0.php',
'qux_2_0.php',
]), $finder->in(self::$tmpDir)->getIterator());

$finder = $this->buildFinder();
$this->assertSame($finder, $finder->exclude('/foo'));
$this->assertIterator($this->toAbsolute([
'test.php',
'test.py',
'toto',
'toto/foo',
'foo bar',
'qux',
'qux/baz_100_1.py',
'qux/baz_1_2.py',
'qux_0_1.php',
'qux_1000_1.php',
'qux_1002_0.php',
'qux_10_2.php',
'qux_12_0.php',
'qux_2_0.php',
]), $finder->in(self::$tmpDir)->getIterator());

/* absolute folders lower than the "root" are not currently supported */
//$finder = $this->buildFinder();
//$this->assertSame($finder, $finder->exclude('/toto/foo'));
//$this->assertIterator($this->toAbsolute([
// 'foo',
// 'foo/bar.tmp',
// 'test.php',
// 'test.py',
// 'toto',
// 'foo bar',
// 'qux',
// 'qux/baz_100_1.py',
// 'qux/baz_1_2.py',
// 'qux_0_1.php',
// 'qux_1000_1.php',
// 'qux_1002_0.php',
// 'qux_10_2.php',
// 'qux_12_0.php',
// 'qux_2_0.php',
//]), $finder->in(self::$tmpDir)->getIterator());
}

public function testIgnoreVCS()
Expand All @@ -355,6 +400,7 @@ public function testIgnoreVCS()
'test.py',
'toto',
'toto/.git',
'toto/foo',
'.bar',
'.foo',
'.foo/.bar',
Expand All @@ -380,6 +426,7 @@ public function testIgnoreVCS()
'test.php',
'test.py',
'toto',
'toto/foo',
'toto/.git',
'.bar',
'.foo',
Expand All @@ -405,6 +452,7 @@ public function testIgnoreVCS()
'test.php',
'test.py',
'toto',
'toto/foo',
'.bar',
'.foo',
'.foo/.bar',
Expand Down Expand Up @@ -468,6 +516,7 @@ public function testIgnoreVCSCanBeDisabledAfterFirstIteration()
'test.php',
'test.py',
'toto',
'toto/foo',
'.bar',
'.foo',
'.foo/.bar',
Expand All @@ -492,6 +541,7 @@ public function testIgnoreVCSCanBeDisabledAfterFirstIteration()
'test.php',
'test.py',
'toto',
'toto/foo',
'toto/.git',
'.bar',
'.foo',
Expand All @@ -517,6 +567,7 @@ public function testIgnoreDotFiles()
'test.py',
'toto',
'toto/.git',
'toto/foo',
'foo bar',
'qux',
'qux/baz_100_1.py',
Expand All @@ -542,6 +593,7 @@ public function testIgnoreDotFiles()
'test.php',
'test.py',
'toto',
'toto/foo',
'toto/.git',
'foo bar',
'qux',
Expand All @@ -563,6 +615,7 @@ public function testIgnoreDotFiles()
'test.php',
'test.py',
'toto',
'toto/foo',
'foo bar',
'qux',
'qux/baz_100_1.py',
Expand Down Expand Up @@ -596,6 +649,7 @@ public function testIgnoreDotFilesCanBeDisabledAfterFirstIteration()
'test.php',
'test.py',
'toto',
'toto/foo',
'foo bar',
]), $finder->getIterator());

Expand All @@ -615,6 +669,7 @@ public function testIgnoreDotFilesCanBeDisabledAfterFirstIteration()
'test.php',
'test.py',
'toto',
'toto/foo',
'.bar',
'.foo',
'.foo/.bar',
Expand Down Expand Up @@ -643,6 +698,7 @@ public function testSortByName()
'test.php',
'test.py',
'toto',
'toto/foo',
]), $finder->in(self::$tmpDir)->getIterator());
}

Expand All @@ -654,6 +710,7 @@ public function testSortByType()
'foo',
'qux',
'toto',
'toto/foo',
'foo bar',
'foo/bar.tmp',
'qux/baz_100_1.py',
Expand All @@ -677,6 +734,7 @@ public function testSortByAccessedTime()
'foo/bar.tmp',
'test.php',
'toto',
'toto/foo',
'test.py',
'foo',
'foo bar',
Expand All @@ -698,6 +756,7 @@ public function testSortByChangedTime()
$this->assertSame($finder, $finder->sortByChangedTime());
$this->assertIterator($this->toAbsolute([
'toto',
'toto/foo',
'test.py',
'test.php',
'foo/bar.tmp',
Expand All @@ -723,6 +782,7 @@ public function testSortByModifiedTime()
'foo/bar.tmp',
'test.php',
'toto',
'toto/foo',
'test.py',
'foo',
'foo bar',
Expand All @@ -744,6 +804,7 @@ public function testReverseSorting()
$this->assertSame($finder, $finder->sortByName());
$this->assertSame($finder, $finder->reverseSorting());
$this->assertOrderedIteratorInForeach($this->toAbsolute([
'toto/foo',
'toto',
'test.py',
'test.php',
Expand Down Expand Up @@ -782,6 +843,7 @@ public function testSortByNameNatural()
'test.php',
'test.py',
'toto',
'toto/foo',
]), $finder->in(self::$tmpDir)->getIterator());

$finder = $this->buildFinder();
Expand All @@ -802,6 +864,7 @@ public function testSortByNameNatural()
'test.php',
'test.py',
'toto',
'toto/foo',
]), $finder->in(self::$tmpDir)->getIterator());
}

Expand All @@ -825,6 +888,7 @@ public function testSort()
'test.php',
'test.py',
'toto',
'toto/foo',
]), $finder->in(self::$tmpDir)->getIterator());
}

Expand Down Expand Up @@ -882,6 +946,7 @@ public function testFollowLinks()
'test.php',
'test.py',
'toto',
'toto/foo',
'foo bar',
'qux',
'qux/baz_100_1.py',
Expand Down Expand Up @@ -972,15 +1037,15 @@ public function testGetIterator()
$dirs[] = (string) $dir;
}

$expected = $this->toAbsolute(['foo', 'qux', 'toto']);
$expected = $this->toAbsolute(['foo', 'qux', 'toto', 'toto/foo']);

sort($dirs);
sort($expected);

$this->assertEquals($expected, $dirs, 'implements the \IteratorAggregate interface');

$finder = $this->buildFinder();
$this->assertEquals(3, iterator_count($finder->directories()->in(self::$tmpDir)), 'implements the \IteratorAggregate interface');
$this->assertEquals(4, iterator_count($finder->directories()->in(self::$tmpDir)), 'implements the \IteratorAggregate interface');

$finder = $this->buildFinder();
$a = iterator_to_array($finder->directories()->in(self::$tmpDir));
Expand All @@ -999,7 +1064,7 @@ public function testRelativePath()
$paths[] = $file->getRelativePath();
}

$ref = ['', '', '', '', '', '', '', '', '', '', '', 'foo', 'qux', 'qux', ''];
$ref = ['', '', '', '', '', '', '', '', '', '', '', 'foo', 'qux', 'qux', '', 'toto'];

sort($ref);
sort($paths);
Expand All @@ -1020,6 +1085,7 @@ public function testRelativePathname()
$ref = [
'test.php',
'toto',
'toto/foo',
'test.py',
'foo',
'foo'.\DIRECTORY_SEPARATOR.'bar.tmp',
Expand Down Expand Up @@ -1056,6 +1122,7 @@ public function testGetFilenameWithoutExtension()
'toto',
'test',
'foo',
'foo',
'bar',
'foo bar',
'qux',
Expand Down Expand Up @@ -1085,7 +1152,7 @@ public function testAppendWithAFinder()

$finder = $finder->append($finder1);

$this->assertIterator($this->toAbsolute(['foo', 'foo/bar.tmp', 'qux', 'toto']), $finder->getIterator());
$this->assertIterator($this->toAbsolute(['foo', 'foo/bar.tmp', 'qux', 'toto', 'toto/foo']), $finder->getIterator());
}

public function testAppendWithAnArray()
Expand Down
Loading
Loading