diff --git a/Iterator/RecursiveDirectoryIterator.php b/Iterator/RecursiveDirectoryIterator.php index 3582e6c1..8bb9b706 100644 --- a/Iterator/RecursiveDirectoryIterator.php +++ b/Iterator/RecursiveDirectoryIterator.php @@ -24,6 +24,7 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator { private bool $ignoreUnreadableDirs; + private bool $ignoreFirstRewind = true; private ?bool $rewindable = null; // these 3 properties take part of the performance optimization to avoid redoing the same work in all iterations @@ -102,7 +103,6 @@ public function getChildren(): \RecursiveDirectoryIterator $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs; // performance optimization to avoid redoing the same work in all children - $children->rewindable = &$this->rewindable; $children->rootPath = $this->rootPath; } @@ -112,36 +112,23 @@ public function getChildren(): \RecursiveDirectoryIterator } } - /** - * Do nothing for non rewindable stream. - */ - public function rewind(): void + public function next(): void { - if (false === $this->isRewindable()) { - return; - } + $this->ignoreFirstRewind = false; - parent::rewind(); + parent::next(); } - /** - * Checks if the stream is rewindable. - */ - public function isRewindable(): bool + public function rewind(): void { - if (null !== $this->rewindable) { - return $this->rewindable; - } - - if (false !== $stream = @opendir($this->getPath())) { - $infos = stream_get_meta_data($stream); - closedir($stream); + // some streams like FTP are not rewindable, ignore the first rewind after creation, + // as newly created DirectoryIterator does not need to be rewound + if ($this->ignoreFirstRewind) { + $this->ignoreFirstRewind = false; - if ($infos['seekable']) { - return $this->rewindable = true; - } + return; } - return $this->rewindable = false; + parent::rewind(); } } diff --git a/Tests/Iterator/RecursiveDirectoryIteratorTest.php b/Tests/Iterator/RecursiveDirectoryIteratorTest.php index f48cc941..3b3caa5e 100644 --- a/Tests/Iterator/RecursiveDirectoryIteratorTest.php +++ b/Tests/Iterator/RecursiveDirectoryIteratorTest.php @@ -15,16 +15,19 @@ class RecursiveDirectoryIteratorTest extends IteratorTestCase { + protected function setUp(): void + { + if (!\in_array('ftp', stream_get_wrappers(), true) || !\ini_get('allow_url_fopen')) { + $this->markTestSkipped('Unsupported stream "ftp".'); + } + } + /** * @group network */ public function testRewindOnFtp() { - try { - $i = new RecursiveDirectoryIterator('ftp://speedtest:speedtest@ftp.otenet.gr/', \RecursiveDirectoryIterator::SKIP_DOTS); - } catch (\UnexpectedValueException $e) { - $this->markTestSkipped('Unsupported stream "ftp".'); - } + $i = new RecursiveDirectoryIterator('ftp://speedtest:speedtest@ftp.otenet.gr/', \RecursiveDirectoryIterator::SKIP_DOTS); $i->rewind(); @@ -36,11 +39,7 @@ public function testRewindOnFtp() */ public function testSeekOnFtp() { - try { - $i = new RecursiveDirectoryIterator('ftp://speedtest:speedtest@ftp.otenet.gr/', \RecursiveDirectoryIterator::SKIP_DOTS); - } catch (\UnexpectedValueException $e) { - $this->markTestSkipped('Unsupported stream "ftp".'); - } + $i = new RecursiveDirectoryIterator('ftp://speedtest:speedtest@ftp.otenet.gr/', \RecursiveDirectoryIterator::SKIP_DOTS); $contains = [ 'ftp://speedtest:speedtest@ftp.otenet.gr'.\DIRECTORY_SEPARATOR.'test100Mb.db',