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>
|
||||
*/
|
||||
class ExcludeDirectoryFilterIterator extends FilterIterator
|
||||
class ExcludeDirectoryFilterIterator extends FilterIterator implements \RecursiveIterator
|
||||
{
|
||||
private $isRecursive;
|
||||
private $patterns;
|
||||
|
||||
/**
|
||||
|
@ -28,6 +29,7 @@ class ExcludeDirectoryFilterIterator extends FilterIterator
|
|||
*/
|
||||
public function __construct(\Iterator $iterator, array $directories)
|
||||
{
|
||||
$this->isRecursive = $iterator instanceof \RecursiveIterator;
|
||||
$this->patterns = array();
|
||||
foreach ($directories as $directory) {
|
||||
$this->patterns[] = '#(^|/)'.preg_quote($directory, '#').'(/|$)#';
|
||||
|
@ -53,4 +55,17 @@ class ExcludeDirectoryFilterIterator extends FilterIterator
|
|||
|
||||
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
|
||||
*/
|
||||
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
|
||||
* rewind in some cases.
|
||||
|
|
|
@ -152,11 +152,11 @@ class FinderTest extends Iterator\RealIteratorTestCase
|
|||
{
|
||||
$finder = $this->buildFinder();
|
||||
$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->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();
|
||||
$this->assertSame($finder, $finder->ignoreVCS(true)->ignoreDotFiles(false));
|
||||
|
@ -167,11 +167,11 @@ class FinderTest extends Iterator\RealIteratorTestCase
|
|||
{
|
||||
$finder = $this->buildFinder();
|
||||
$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->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();
|
||||
$this->assertSame($finder, $finder->ignoreDotFiles(true)->ignoreVCS(false));
|
||||
|
|
|
@ -37,6 +37,7 @@ class DateRangeFilterIteratorTest extends RealIteratorTestCase
|
|||
'foo/bar.tmp',
|
||||
'test.php',
|
||||
'toto',
|
||||
'toto/.git',
|
||||
'.bar',
|
||||
'.foo',
|
||||
'.foo/.bar',
|
||||
|
@ -49,6 +50,7 @@ class DateRangeFilterIteratorTest extends RealIteratorTestCase
|
|||
'test.py',
|
||||
'foo',
|
||||
'toto',
|
||||
'toto/.git',
|
||||
'.bar',
|
||||
'.foo',
|
||||
'.foo/.bar',
|
||||
|
@ -62,6 +64,7 @@ class DateRangeFilterIteratorTest extends RealIteratorTestCase
|
|||
'foo/bar.tmp',
|
||||
'test.php',
|
||||
'toto',
|
||||
'toto/.git',
|
||||
'.foo',
|
||||
);
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ class DepthRangeFilterIteratorTest extends RealIteratorTestCase
|
|||
'foo/bar.tmp',
|
||||
'test.php',
|
||||
'toto',
|
||||
'toto/.git',
|
||||
'.foo',
|
||||
'.foo/.bar',
|
||||
'.bar',
|
||||
|
@ -58,12 +59,14 @@ class DepthRangeFilterIteratorTest extends RealIteratorTestCase
|
|||
);
|
||||
|
||||
$graterThanOrEqualTo1 = array(
|
||||
'toto/.git',
|
||||
'foo/bar.tmp',
|
||||
'.foo/.bar',
|
||||
'.foo/bar',
|
||||
);
|
||||
|
||||
$equalTo1 = array(
|
||||
'toto/.git',
|
||||
'foo/bar.tmp',
|
||||
'.foo/.bar',
|
||||
'.foo/bar',
|
||||
|
|
|
@ -39,6 +39,7 @@ class ExcludeDirectoryFilterIteratorTest extends RealIteratorTestCase
|
|||
'test.py',
|
||||
'test.php',
|
||||
'toto',
|
||||
'toto/.git',
|
||||
'foo bar',
|
||||
);
|
||||
|
||||
|
@ -53,6 +54,7 @@ class ExcludeDirectoryFilterIteratorTest extends RealIteratorTestCase
|
|||
'foo/bar.tmp',
|
||||
'test.php',
|
||||
'toto',
|
||||
'toto/.git',
|
||||
'foo bar',
|
||||
);
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ class FileTypeFilterIteratorTest extends RealIteratorTestCase
|
|||
'.git',
|
||||
'foo',
|
||||
'toto',
|
||||
'toto/.git',
|
||||
'.foo',
|
||||
);
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ abstract class RealIteratorTestCase extends IteratorTestCase
|
|||
'foo/bar.tmp',
|
||||
'test.php',
|
||||
'toto/',
|
||||
'toto/.git/',
|
||||
'foo bar',
|
||||
);
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ class SizeRangeFilterIteratorTest extends RealIteratorTestCase
|
|||
'foo',
|
||||
'test.php',
|
||||
'toto',
|
||||
'toto/.git',
|
||||
);
|
||||
|
||||
return array(
|
||||
|
|
|
@ -85,6 +85,7 @@ class SortableIteratorTest extends RealIteratorTestCase
|
|||
'test.php',
|
||||
'test.py',
|
||||
'toto',
|
||||
'toto/.git',
|
||||
);
|
||||
|
||||
$sortByType = array(
|
||||
|
@ -92,6 +93,7 @@ class SortableIteratorTest extends RealIteratorTestCase
|
|||
'.git',
|
||||
'foo',
|
||||
'toto',
|
||||
'toto/.git',
|
||||
'.bar',
|
||||
'.foo/.bar',
|
||||
'.foo/bar',
|
||||
|
@ -113,6 +115,7 @@ class SortableIteratorTest extends RealIteratorTestCase
|
|||
'test.php',
|
||||
'test.py',
|
||||
'toto',
|
||||
'toto/.git',
|
||||
);
|
||||
|
||||
$sortByAccessedTime = array(
|
||||
|
@ -127,6 +130,7 @@ class SortableIteratorTest extends RealIteratorTestCase
|
|||
'test.py',
|
||||
'foo',
|
||||
'toto',
|
||||
'toto/.git',
|
||||
'foo bar',
|
||||
),
|
||||
// This file was accessed after sleeping for 1 sec
|
||||
|
@ -143,6 +147,7 @@ class SortableIteratorTest extends RealIteratorTestCase
|
|||
'foo',
|
||||
'foo/bar.tmp',
|
||||
'toto',
|
||||
'toto/.git',
|
||||
'foo bar',
|
||||
),
|
||||
array('test.php'),
|
||||
|
@ -159,6 +164,7 @@ class SortableIteratorTest extends RealIteratorTestCase
|
|||
'foo',
|
||||
'foo/bar.tmp',
|
||||
'toto',
|
||||
'toto/.git',
|
||||
'foo bar',
|
||||
),
|
||||
array('test.php'),
|
||||
|
|
Reference in New Issue