minor #15824 [Finder] Fix recursive filter iterator (nicolas-grekas)
This PR was merged into the 2.3 branch.
Discussion
----------
[Finder] Fix recursive filter iterator
| Q | A
| ------------- | ---
| Bug fix? | yes
| New feature? | no
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #15802
| License | MIT
| Doc PR | -
#15802 was broken because the filters where not propagated to children iterators. This fixes the issue and adds a test case for this situation. The RecursiveIterator implementation is moved from FilterIterator to ExcludeDirectoryFilterIterator. Doing so on other filters is possible but would be a new feature that is not required for fixing the performance issue we had previously.
Commits
-------
cf3019b
[Finder] Fix recursive filter iterator
This commit is contained in:
commit
4a9676b5a2
@ -16,8 +16,9 @@ namespace Symfony\Component\Finder\Iterator;
|
|||||||
*
|
*
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
*/
|
*/
|
||||||
class ExcludeDirectoryFilterIterator extends FilterIterator
|
class ExcludeDirectoryFilterIterator extends FilterIterator implements \RecursiveIterator
|
||||||
{
|
{
|
||||||
|
private $isRecursive;
|
||||||
private $patterns;
|
private $patterns;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,6 +29,7 @@ class ExcludeDirectoryFilterIterator extends FilterIterator
|
|||||||
*/
|
*/
|
||||||
public function __construct(\Iterator $iterator, array $directories)
|
public function __construct(\Iterator $iterator, array $directories)
|
||||||
{
|
{
|
||||||
|
$this->isRecursive = $iterator instanceof \RecursiveIterator;
|
||||||
$this->patterns = array();
|
$this->patterns = array();
|
||||||
foreach ($directories as $directory) {
|
foreach ($directories as $directory) {
|
||||||
$this->patterns[] = '#(^|/)'.preg_quote($directory, '#').'(/|$)#';
|
$this->patterns[] = '#(^|/)'.preg_quote($directory, '#').'(/|$)#';
|
||||||
@ -53,4 +55,17 @@ class ExcludeDirectoryFilterIterator extends FilterIterator
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function hasChildren()
|
||||||
|
{
|
||||||
|
return $this->isRecursive && $this->getInnerIterator()->hasChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getChildren()
|
||||||
|
{
|
||||||
|
$children = new self($this->getInnerIterator()->getChildren(), array());
|
||||||
|
$children->patterns = $this->patterns;
|
||||||
|
|
||||||
|
return $children;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,18 +18,8 @@ namespace Symfony\Component\Finder\Iterator;
|
|||||||
*
|
*
|
||||||
* @author Alex Bogomazov
|
* @author Alex Bogomazov
|
||||||
*/
|
*/
|
||||||
abstract class FilterIterator extends \FilterIterator implements \RecursiveIterator
|
abstract class FilterIterator extends \FilterIterator
|
||||||
{
|
{
|
||||||
public function hasChildren()
|
|
||||||
{
|
|
||||||
return $this->getInnerIterator() instanceof \RecursiveIterator && $this->getInnerIterator()->hasChildren();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getChildren()
|
|
||||||
{
|
|
||||||
return $this->getInnerIterator()->getChildren();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a workaround for the problem with \FilterIterator leaving inner \FilesystemIterator in wrong state after
|
* This is a workaround for the problem with \FilterIterator leaving inner \FilesystemIterator in wrong state after
|
||||||
* rewind in some cases.
|
* rewind in some cases.
|
||||||
|
@ -152,11 +152,11 @@ class FinderTest extends Iterator\RealIteratorTestCase
|
|||||||
{
|
{
|
||||||
$finder = $this->buildFinder();
|
$finder = $this->buildFinder();
|
||||||
$this->assertSame($finder, $finder->ignoreVCS(false)->ignoreDotFiles(false));
|
$this->assertSame($finder, $finder->ignoreVCS(false)->ignoreDotFiles(false));
|
||||||
$this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
|
$this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'toto/.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
|
||||||
|
|
||||||
$finder = $this->buildFinder();
|
$finder = $this->buildFinder();
|
||||||
$finder->ignoreVCS(false)->ignoreVCS(false)->ignoreDotFiles(false);
|
$finder->ignoreVCS(false)->ignoreVCS(false)->ignoreDotFiles(false);
|
||||||
$this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
|
$this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'toto/.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
|
||||||
|
|
||||||
$finder = $this->buildFinder();
|
$finder = $this->buildFinder();
|
||||||
$this->assertSame($finder, $finder->ignoreVCS(true)->ignoreDotFiles(false));
|
$this->assertSame($finder, $finder->ignoreVCS(true)->ignoreDotFiles(false));
|
||||||
@ -167,11 +167,11 @@ class FinderTest extends Iterator\RealIteratorTestCase
|
|||||||
{
|
{
|
||||||
$finder = $this->buildFinder();
|
$finder = $this->buildFinder();
|
||||||
$this->assertSame($finder, $finder->ignoreDotFiles(false)->ignoreVCS(false));
|
$this->assertSame($finder, $finder->ignoreDotFiles(false)->ignoreVCS(false));
|
||||||
$this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
|
$this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'toto/.git', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
|
||||||
|
|
||||||
$finder = $this->buildFinder();
|
$finder = $this->buildFinder();
|
||||||
$finder->ignoreDotFiles(false)->ignoreDotFiles(false)->ignoreVCS(false);
|
$finder->ignoreDotFiles(false)->ignoreDotFiles(false)->ignoreVCS(false);
|
||||||
$this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
|
$this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'toto/.git', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
|
||||||
|
|
||||||
$finder = $this->buildFinder();
|
$finder = $this->buildFinder();
|
||||||
$this->assertSame($finder, $finder->ignoreDotFiles(true)->ignoreVCS(false));
|
$this->assertSame($finder, $finder->ignoreDotFiles(true)->ignoreVCS(false));
|
||||||
|
@ -37,6 +37,7 @@ class DateRangeFilterIteratorTest extends RealIteratorTestCase
|
|||||||
'foo/bar.tmp',
|
'foo/bar.tmp',
|
||||||
'test.php',
|
'test.php',
|
||||||
'toto',
|
'toto',
|
||||||
|
'toto/.git',
|
||||||
'.bar',
|
'.bar',
|
||||||
'.foo',
|
'.foo',
|
||||||
'.foo/.bar',
|
'.foo/.bar',
|
||||||
@ -49,6 +50,7 @@ class DateRangeFilterIteratorTest extends RealIteratorTestCase
|
|||||||
'test.py',
|
'test.py',
|
||||||
'foo',
|
'foo',
|
||||||
'toto',
|
'toto',
|
||||||
|
'toto/.git',
|
||||||
'.bar',
|
'.bar',
|
||||||
'.foo',
|
'.foo',
|
||||||
'.foo/.bar',
|
'.foo/.bar',
|
||||||
@ -62,6 +64,7 @@ class DateRangeFilterIteratorTest extends RealIteratorTestCase
|
|||||||
'foo/bar.tmp',
|
'foo/bar.tmp',
|
||||||
'test.php',
|
'test.php',
|
||||||
'toto',
|
'toto',
|
||||||
|
'toto/.git',
|
||||||
'.foo',
|
'.foo',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ class DepthRangeFilterIteratorTest extends RealIteratorTestCase
|
|||||||
'foo/bar.tmp',
|
'foo/bar.tmp',
|
||||||
'test.php',
|
'test.php',
|
||||||
'toto',
|
'toto',
|
||||||
|
'toto/.git',
|
||||||
'.foo',
|
'.foo',
|
||||||
'.foo/.bar',
|
'.foo/.bar',
|
||||||
'.bar',
|
'.bar',
|
||||||
@ -58,12 +59,14 @@ class DepthRangeFilterIteratorTest extends RealIteratorTestCase
|
|||||||
);
|
);
|
||||||
|
|
||||||
$graterThanOrEqualTo1 = array(
|
$graterThanOrEqualTo1 = array(
|
||||||
|
'toto/.git',
|
||||||
'foo/bar.tmp',
|
'foo/bar.tmp',
|
||||||
'.foo/.bar',
|
'.foo/.bar',
|
||||||
'.foo/bar',
|
'.foo/bar',
|
||||||
);
|
);
|
||||||
|
|
||||||
$equalTo1 = array(
|
$equalTo1 = array(
|
||||||
|
'toto/.git',
|
||||||
'foo/bar.tmp',
|
'foo/bar.tmp',
|
||||||
'.foo/.bar',
|
'.foo/.bar',
|
||||||
'.foo/bar',
|
'.foo/bar',
|
||||||
|
@ -39,6 +39,7 @@ class ExcludeDirectoryFilterIteratorTest extends RealIteratorTestCase
|
|||||||
'test.py',
|
'test.py',
|
||||||
'test.php',
|
'test.php',
|
||||||
'toto',
|
'toto',
|
||||||
|
'toto/.git',
|
||||||
'foo bar',
|
'foo bar',
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -53,6 +54,7 @@ class ExcludeDirectoryFilterIteratorTest extends RealIteratorTestCase
|
|||||||
'foo/bar.tmp',
|
'foo/bar.tmp',
|
||||||
'test.php',
|
'test.php',
|
||||||
'toto',
|
'toto',
|
||||||
|
'toto/.git',
|
||||||
'foo bar',
|
'foo bar',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ class FileTypeFilterIteratorTest extends RealIteratorTestCase
|
|||||||
'.git',
|
'.git',
|
||||||
'foo',
|
'foo',
|
||||||
'toto',
|
'toto',
|
||||||
|
'toto/.git',
|
||||||
'.foo',
|
'.foo',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ abstract class RealIteratorTestCase extends IteratorTestCase
|
|||||||
'foo/bar.tmp',
|
'foo/bar.tmp',
|
||||||
'test.php',
|
'test.php',
|
||||||
'toto/',
|
'toto/',
|
||||||
|
'toto/.git/',
|
||||||
'foo bar',
|
'foo bar',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ class SizeRangeFilterIteratorTest extends RealIteratorTestCase
|
|||||||
'foo',
|
'foo',
|
||||||
'test.php',
|
'test.php',
|
||||||
'toto',
|
'toto',
|
||||||
|
'toto/.git',
|
||||||
);
|
);
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
@ -85,6 +85,7 @@ class SortableIteratorTest extends RealIteratorTestCase
|
|||||||
'test.php',
|
'test.php',
|
||||||
'test.py',
|
'test.py',
|
||||||
'toto',
|
'toto',
|
||||||
|
'toto/.git',
|
||||||
);
|
);
|
||||||
|
|
||||||
$sortByType = array(
|
$sortByType = array(
|
||||||
@ -92,6 +93,7 @@ class SortableIteratorTest extends RealIteratorTestCase
|
|||||||
'.git',
|
'.git',
|
||||||
'foo',
|
'foo',
|
||||||
'toto',
|
'toto',
|
||||||
|
'toto/.git',
|
||||||
'.bar',
|
'.bar',
|
||||||
'.foo/.bar',
|
'.foo/.bar',
|
||||||
'.foo/bar',
|
'.foo/bar',
|
||||||
@ -113,6 +115,7 @@ class SortableIteratorTest extends RealIteratorTestCase
|
|||||||
'test.php',
|
'test.php',
|
||||||
'test.py',
|
'test.py',
|
||||||
'toto',
|
'toto',
|
||||||
|
'toto/.git',
|
||||||
);
|
);
|
||||||
|
|
||||||
$sortByAccessedTime = array(
|
$sortByAccessedTime = array(
|
||||||
@ -127,6 +130,7 @@ class SortableIteratorTest extends RealIteratorTestCase
|
|||||||
'test.py',
|
'test.py',
|
||||||
'foo',
|
'foo',
|
||||||
'toto',
|
'toto',
|
||||||
|
'toto/.git',
|
||||||
'foo bar',
|
'foo bar',
|
||||||
),
|
),
|
||||||
// This file was accessed after sleeping for 1 sec
|
// This file was accessed after sleeping for 1 sec
|
||||||
@ -143,6 +147,7 @@ class SortableIteratorTest extends RealIteratorTestCase
|
|||||||
'foo',
|
'foo',
|
||||||
'foo/bar.tmp',
|
'foo/bar.tmp',
|
||||||
'toto',
|
'toto',
|
||||||
|
'toto/.git',
|
||||||
'foo bar',
|
'foo bar',
|
||||||
),
|
),
|
||||||
array('test.php'),
|
array('test.php'),
|
||||||
@ -159,6 +164,7 @@ class SortableIteratorTest extends RealIteratorTestCase
|
|||||||
'foo',
|
'foo',
|
||||||
'foo/bar.tmp',
|
'foo/bar.tmp',
|
||||||
'toto',
|
'toto',
|
||||||
|
'toto/.git',
|
||||||
'foo bar',
|
'foo bar',
|
||||||
),
|
),
|
||||||
array('test.php'),
|
array('test.php'),
|
||||||
|
Reference in New Issue
Block a user