From d3f03bee5ccd783f5405d67dfc2ec0adf5dbaadc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Wed, 5 Jul 2023 12:31:53 +0200 Subject: [PATCH] [Finder] Fix initial directory is opened twice --- .../Iterator/RecursiveDirectoryIterator.php | 37 +++++++------------ .../RecursiveDirectoryIteratorTest.php | 19 +++++----- 2 files changed, 22 insertions(+), 34 deletions(-) diff --git a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php index 27589cdd5f57a..886dae588530b 100644 --- a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php +++ b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php @@ -29,7 +29,7 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator /** * @var bool */ - private $rewindable; + private $ignoreFirstRewind = true; // these 3 properties take part of the performance optimization to avoid redoing the same work in all iterations private $rootPath; @@ -118,7 +118,6 @@ public function getChildren() $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs; // performance optimization to avoid redoing the same work in all children - $children->rewindable = &$this->rewindable; $children->rootPath = $this->rootPath; } @@ -129,40 +128,30 @@ public function getChildren() } /** - * Do nothing for non rewindable stream. - * * @return void */ #[\ReturnTypeWillChange] - public function rewind() + public function next() { - if (false === $this->isRewindable()) { - return; - } + $this->ignoreFirstRewind = false; - parent::rewind(); + parent::next(); } /** - * Checks if the stream is rewindable. - * - * @return bool + * @return void */ - public function isRewindable() + #[\ReturnTypeWillChange] + public function rewind() { - 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/src/Symfony/Component/Finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php index f48cc941f8ad3..3b3caa5e3f789 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php +++ b/src/Symfony/Component/Finder/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',