From b637b21fa87dc4e5d20933fee141dd9fb89e598b Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Tue, 10 Aug 2021 20:59:52 +0200 Subject: [PATCH] [Finder] Move check for unreachable dirs to hasChildren() Signed-off-by: Alexander M. Turek --- .../Iterator/RecursiveDirectoryIterator.php | 63 +++++++++++++++++-- 1 file changed, 59 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php index a18e6185beeec..447b3e3526a2e 100644 --- a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php +++ b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php @@ -36,6 +36,11 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator private $subPath; private $directorySeparator = '/'; + /** + * @var \RecursiveDirectoryIterator|null + */ + private $children; + /** * @throws \RuntimeException */ @@ -53,6 +58,17 @@ public function __construct(string $path, int $flags, bool $ignoreUnreadableDirs } } + /** + * @return void + */ + #[\ReturnTypeWillChange] + public function next() + { + $this->children = null; + + parent::next(); + } + /** * Return an instance of SplFileInfo with support for relative paths. * @@ -79,7 +95,30 @@ public function current() } /** - * @return \RecursiveIterator + * {@inheritdoc} + * + * @return bool + */ + #[\ReturnTypeWillChange] + public function hasChildren($allowLinks = false) + { + $hasChildren = parent::hasChildren($allowLinks); + + if (!$hasChildren || !$this->ignoreUnreadableDirs) { + return $hasChildren; + } + + try { + $this->children = parent::getChildren(); + } catch (\UnexpectedValueException $e) { + return false; + } + + return true; + } + + /** + * @return \RecursiveDirectoryIterator * * @throws AccessDeniedException */ @@ -87,7 +126,7 @@ public function current() public function getChildren() { try { - $children = parent::getChildren(); + $children = $this->children ?? parent::getChildren(); if ($children instanceof self) { // parent method will call the constructor with default arguments, so unreadable dirs won't be ignored anymore @@ -100,12 +139,15 @@ public function getChildren() return $children; } catch (\UnexpectedValueException $e) { + // @deprecated The if block can be removed in 6.0. if ($this->ignoreUnreadableDirs) { + trigger_deprecation('symfony/finder', '5.4', 'Calling "%s" if "hasChildren()" returns false is deprecated.', __METHOD__); + // If directory is unreadable and finder is set to ignore it, a fake empty content is returned. return new \RecursiveArrayIterator([]); - } else { - throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e); } + + throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e); } } @@ -117,6 +159,8 @@ public function getChildren() #[\ReturnTypeWillChange] public function rewind() { + $this->children = null; + if (false === $this->isRewindable()) { return; } @@ -124,6 +168,17 @@ public function rewind() parent::rewind(); } + /** + * @return void + */ + #[\ReturnTypeWillChange] + public function seek($offset) + { + $this->children = null; + + parent::seek($offset); + } + /** * Checks if the stream is rewindable. *