Permalink
Browse files

[Finder] Workaround for FilterIterator-FilesystemIterator-rewind issue

  • Loading branch information...
1 parent 4c08f33 commit cd803f2f0c351b110dfa70161ceb2cbeb03341b2 @alebo alebo committed Jul 20, 2012
@@ -19,7 +19,7 @@
*
* @author Fabien Potencier <fabien@symfony.com>
*/
-class CustomFilterIterator extends \FilterIterator
+class CustomFilterIterator extends FilterIterator
{
private $filters = array();
@@ -16,7 +16,7 @@
*
* @author Fabien Potencier <fabien@symfony.com>
*/
-class DateRangeFilterIterator extends \FilterIterator
+class DateRangeFilterIterator extends FilterIterator
{
private $comparators = array();
@@ -16,7 +16,7 @@
*
* @author Fabien Potencier <fabien@symfony.com>
*/
-class DepthRangeFilterIterator extends \FilterIterator
+class DepthRangeFilterIterator extends FilterIterator
{
private $minDepth = 0;
@@ -16,7 +16,7 @@
*
* @author Fabien Potencier <fabien@symfony.com>
*/
-class ExcludeDirectoryFilterIterator extends \FilterIterator
+class ExcludeDirectoryFilterIterator extends FilterIterator
{
private $patterns;
@@ -16,7 +16,7 @@
*
* @author Fabien Potencier <fabien@symfony.com>
*/
-class FileTypeFilterIterator extends \FilterIterator
+class FileTypeFilterIterator extends FilterIterator
{
const ONLY_FILES = 1;
const ONLY_DIRECTORIES = 2;
@@ -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();
+ }
+}
@@ -16,7 +16,7 @@
*
* @author Fabien Potencier <fabien@symfony.com>
*/
-abstract class MultiplePcreFilterIterator extends \FilterIterator
+abstract class MultiplePcreFilterIterator extends FilterIterator
{
protected $matchRegexps;
protected $noMatchRegexps;
@@ -16,7 +16,7 @@
*
* @author Fabien Potencier <fabien@symfony.com>
*/
-class SizeRangeFilterIterator extends \FilterIterator
+class SizeRangeFilterIterator extends FilterIterator
{
private $comparators = array();
View
@@ -440,4 +440,23 @@ public function testNotContainsOnDirectory()
$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));
+ }
}
@@ -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);
+ }
+}

0 comments on commit cd803f2

Please sign in to comment.