Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
42.86% |
3 / 7 |
CRAP | |
80.49% |
33 / 41 |
| GekRecursiveDirectoryIterator | |
0.00% |
0 / 1 |
|
42.86% |
3 / 7 |
22.97 | |
80.49% |
33 / 41 |
| __construct | |
0.00% |
0 / 1 |
4.03 | |
87.50% |
7 / 8 |
|||
| current | |
100.00% |
1 / 1 |
4 | |
100.00% |
8 / 8 |
|||
| getChildren | |
0.00% |
0 / 1 |
5.02 | |
60.00% |
6 / 10 |
|||
| isIgnoreUnreadableDirs | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| setIgnoreUnreadableDirs | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| rewind | |
100.00% |
1 / 1 |
2 | |
100.00% |
4 / 4 |
|||
| isRewindable | |
100.00% |
1 / 1 |
4 | |
100.00% |
8 / 8 |
|||
| <?php | |
| namespace Gek\FileFinder\Iterators; | |
| use Gek\FileFinder\FileInfo; | |
| use RecursiveDirectoryIterator; | |
| class GekRecursiveDirectoryIterator extends RecursiveDirectoryIterator | |
| { | |
| /** | |
| * @var bool | |
| */ | |
| private $ignoreUnreadableDirs; | |
| /** | |
| * @var bool | |
| */ | |
| private $rewindable; | |
| // these 3 properties take part of the performance optimization to avoid redoing the same work in all iterations | |
| private $rootPath; | |
| private $subPath; | |
| private $directorySeparator = '/'; | |
| /** | |
| * GekRecursiveDirectoryIterator constructor. | |
| * @param string $path | |
| * @param int $flags | |
| * @param bool $ignoreUnreadableDirs | |
| */ | |
| public function __construct(string $path, int $flags, bool $ignoreUnreadableDirs = false) | |
| { | |
| if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) { | |
| throw new \RuntimeException('This iterator only support returning current as fileinfo.'); | |
| } | |
| parent::__construct($path, $flags); | |
| $this->ignoreUnreadableDirs = $ignoreUnreadableDirs; | |
| $this->rootPath = $path; | |
| if ('/' !== \DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) { | |
| $this->directorySeparator = \DIRECTORY_SEPARATOR; | |
| } | |
| } | |
| /** | |
| * @return FileInfo | |
| */ | |
| public function current() | |
| { | |
| // the logic here avoids redoing the same work in all iterations | |
| if (null === $subPathname = $this->subPath) { | |
| $subPathname = $this->subPath = (string) $this->getSubPath(); | |
| } | |
| if ('' !== $subPathname) { | |
| $subPathname .= $this->directorySeparator; | |
| } | |
| $subPathname .= $this->getFilename(); | |
| if ('/' !== $basePath = $this->rootPath) { | |
| $basePath .= $this->directorySeparator; | |
| } | |
| return new FileInfo($basePath.$subPathname, $this->subPath, $subPathname); | |
| } | |
| public function getChildren() | |
| { | |
| try { | |
| $children = parent::getChildren(); | |
| if ($children instanceof self) { | |
| // parent method will call the constructor with default arguments, so unreadable dirs won't be ignored anymore | |
| $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs; | |
| // performance optimization to avoid redoing the same work in all children | |
| $children->rewindable = &$this->rewindable; | |
| $children->rootPath = $this->rootPath; | |
| } | |
| return $children; | |
| } catch (\UnexpectedValueException $e) { | |
| if ($this->ignoreUnreadableDirs) { | |
| // If directory is unreadable and finder is set to ignore it, a fake empty content is returned. | |
| return new \RecursiveArrayIterator([]); | |
| } else { | |
| throw new \UnexpectedValueException($e->getMessage(), $e->getCode(), $e); | |
| } | |
| } | |
| } | |
| /** | |
| * @return bool | |
| */ | |
| public function isIgnoreUnreadableDirs(): bool | |
| { | |
| return $this->ignoreUnreadableDirs; | |
| } | |
| /** | |
| * @param bool $ignoreUnreadableDirs | |
| */ | |
| public function setIgnoreUnreadableDirs(bool $ignoreUnreadableDirs): void | |
| { | |
| $this->ignoreUnreadableDirs = $ignoreUnreadableDirs; | |
| } | |
| /** | |
| * Do nothing for non rewindable stream. | |
| */ | |
| public function rewind() | |
| { | |
| if (false === $this->isRewindable()) { | |
| return; | |
| } | |
| parent::rewind(); | |
| } | |
| /** | |
| * Checks if the stream is rewindable. | |
| * | |
| * @return bool true when the stream is rewindable, false otherwise | |
| */ | |
| public function isRewindable() | |
| { | |
| if (null !== $this->rewindable) { | |
| return $this->rewindable; | |
| } | |
| if (false !== $stream = @opendir($this->getPath())) { | |
| $infos = stream_get_meta_data($stream); | |
| closedir($stream); | |
| if ($infos['seekable']) { | |
| return $this->rewindable = true; | |
| } | |
| } | |
| return $this->rewindable = false; | |
| } | |
| } |