[Finder] Workaround for FilterIterator-FilesystemIterator-rewind issue

This commit is contained in:
Alex Bogomazov 2012-07-20 13:02:47 +03:00
parent 9f157a1616
commit ae6016c6fc
10 changed files with 111 additions and 7 deletions

View File

@ -19,7 +19,7 @@ namespace Symfony\Component\Finder\Iterator;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class CustomFilterIterator extends \FilterIterator
class CustomFilterIterator extends FilterIterator
{
private $filters = array();

View File

@ -16,7 +16,7 @@ namespace Symfony\Component\Finder\Iterator;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class DateRangeFilterIterator extends \FilterIterator
class DateRangeFilterIterator extends FilterIterator
{
private $comparators = array();

View File

@ -16,7 +16,7 @@ namespace Symfony\Component\Finder\Iterator;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class DepthRangeFilterIterator extends \FilterIterator
class DepthRangeFilterIterator extends FilterIterator
{
private $minDepth = 0;

View File

@ -16,7 +16,7 @@ namespace Symfony\Component\Finder\Iterator;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class ExcludeDirectoryFilterIterator extends \FilterIterator
class ExcludeDirectoryFilterIterator extends FilterIterator
{
private $patterns;

View File

@ -16,7 +16,7 @@ namespace Symfony\Component\Finder\Iterator;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class FileTypeFilterIterator extends \FilterIterator
class FileTypeFilterIterator extends FilterIterator
{
const ONLY_FILES = 1;
const ONLY_DIRECTORIES = 2;

View File

@ -0,0 +1,39 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Alex Bogomazov
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Finder\Iterator;
/**
* This iterator just overrides the rewind method in order to correct a PHP bug.
*
* @author Alex Bogomazov
*/
abstract class FilterIterator extends \FilterIterator
{
/**
* This is a workaround for the problem with \FilterIterator leaving inner \FilesystemIterator in wrong state after
* rewind in some cases.
* @see FilterIterator::rewind()
*/
public function rewind()
{
$iterator = $this;
while ($iterator instanceof \OuterIterator) {
if ($iterator->getInnerIterator() instanceof \FilesystemIterator) {
$iterator->getInnerIterator()->next();
$iterator->getInnerIterator()->rewind();
}
$iterator = $iterator->getInnerIterator();
}
parent::rewind();
}
}

View File

@ -16,7 +16,7 @@ namespace Symfony\Component\Finder\Iterator;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
abstract class MultiplePcreFilterIterator extends \FilterIterator
abstract class MultiplePcreFilterIterator extends FilterIterator
{
protected $matchRegexps;
protected $noMatchRegexps;

View File

@ -16,7 +16,7 @@ namespace Symfony\Component\Finder\Iterator;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class SizeRangeFilterIterator extends \FilterIterator
class SizeRangeFilterIterator extends FilterIterator
{
private $comparators = array();

View File

@ -440,4 +440,23 @@ class FinderTest extends Iterator\RealIteratorTestCase
$this->assertIterator(array(), $finder);
}
/**
* Searching in multiple locations involves AppendIterator which does an unnecessary rewind which leaves FilterIterator
* with inner FilesystemIterator in an ivalid state.
*/
public function testMultipleLocations()
{
$tmpDir = sys_get_temp_dir() . '/symfony2_finder';
$locations = array(
$tmpDir . '/',
$tmpDir . '/toto/',
);
// it is expected that there are test.py test.php in the tmpDir
$finder = new Finder();
$finder->in($locations)->depth('< 1')->name('test.php');
$this->assertEquals(1, count($finder));
}
}

View File

@ -0,0 +1,46 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Alex Bogomazov
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Finder\Tests\Iterator;
class FilterIteratorTest extends RealIteratorTestCase
{
public function testFilterFilesystemIterators()
{
$tmpDir = sys_get_temp_dir().'/symfony2_finder';
$i = new \FilesystemIterator($tmpDir);
// it is expected that there are test.py test.php in the tmpDir
$i = $this->getMockForAbstractClass('Symfony\Component\Finder\Iterator\FilterIterator', array($i));
$i->expects($this->any())->method('accept')->will($this->returnCallback(function () use ($i) {
return (bool)preg_match('/\.php/', (string)$i->current());
}));
$c = 0;
foreach ($i as $item) {
$c++;
}
// This works
$this->assertEquals(1, $c);
$i->rewind();
$c = 0;
foreach ($i as $item) {
$c++;
}
// This would fail with \FilterIterator but works with Symfony\Component\Finder\Iterator\FilterIterator
$this->assertEquals(1, $c);
}
}