diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 11:46:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 11:46:43 +0000 |
commit | 3e02d5aff85babc3ffbfcf52313f2108e313aa23 (patch) | |
tree | b01f3923360c20a6a504aff42d45670c58af3ec5 /library/Icinga/Util/DirectoryIterator.php | |
parent | Initial commit. (diff) | |
download | icingaweb2-3e02d5aff85babc3ffbfcf52313f2108e313aa23.tar.xz icingaweb2-3e02d5aff85babc3ffbfcf52313f2108e313aa23.zip |
Adding upstream version 2.12.1.upstream/2.12.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/Icinga/Util/DirectoryIterator.php')
-rw-r--r-- | library/Icinga/Util/DirectoryIterator.php | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/library/Icinga/Util/DirectoryIterator.php b/library/Icinga/Util/DirectoryIterator.php new file mode 100644 index 0000000..cee37b6 --- /dev/null +++ b/library/Icinga/Util/DirectoryIterator.php @@ -0,0 +1,214 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Util; + +use ArrayIterator; +use InvalidArgumentException; +use RecursiveIterator; + +/** + * Iterator for traversing a directory + */ +class DirectoryIterator implements RecursiveIterator +{ + /** + * Iterate files first + * + * @var int + */ + const FILES_FIRST = 1; + + /** + * Current directory item + * + * @var string|false + */ + private $current; + + /** + * The file extension to filter for + * + * @var string + */ + protected $extension; + + /** + * Scanned files + * + * @var ArrayIterator + */ + private $files; + + /** + * Iterator flags + * + * @var int + */ + protected $flags; + + /** + * Current key + * + * @var string|false + */ + private $key; + + /** + * The path of the directory to traverse + * + * @var string + */ + protected $path; + + /** + * Directory queue if FILES_FIRST flag is set + * + * @var array + */ + private $queue; + + /** + * Whether to skip empty files + * + * Defaults to true. + * + * @var bool + */ + protected $skipEmpty = true; + + /** + * Whether to skip hidden files + * + * Defaults to true. + * + * @var bool + */ + protected $skipHidden = true; + + /** + * Create a new directory iterator from path + * + * The given path will not be validated whether it is readable. Use {@link isReadable()} before creating a new + * directory iterator instance. + * + * @param string $path The path of the directory to traverse + * @param string $extension The file extension to filter for. A leading dot is optional + * @param int $flags Iterator flags + */ + public function __construct($path, $extension = null, $flags = null) + { + if (empty($path)) { + throw new InvalidArgumentException('The path can\'t be empty'); + } + $this->path = $path; + if (! empty($extension)) { + $this->extension = '.' . ltrim($extension, '.'); + } + if ($flags !== null) { + $this->flags = $flags; + } + } + + /** + * Check whether the given path is a directory and is readable + * + * @param string $path The path of the directory + * + * @return bool + */ + public static function isReadable($path) + { + return is_dir($path) && is_readable($path); + } + + public function hasChildren(): bool + { + return static::isReadable($this->current); + } + + public function getChildren(): DirectoryIterator + { + return new static($this->current, $this->extension, $this->flags); + } + + #[\ReturnTypeWillChange] + public function current() + { + return $this->current; + } + + public function next(): void + { + $path = null; + do { + $this->files->next(); + $skip = false; + if (! $this->files->valid()) { + $file = false; + $path = false; + break; + } else { + $file = $this->files->current(); + do { + if ($this->skipHidden && $file[0] === '.') { + $skip = true; + break; + } + + $path = $this->path . '/' . $file; + + if (is_dir($path)) { + if ($this->flags & static::FILES_FIRST === static::FILES_FIRST) { + $this->queue[] = array($path, $file); + $skip = true; + } + break; + } + + if ($this->skipEmpty && ! filesize($path)) { + $skip = true; + break; + } + + if ($this->extension && ! StringHelper::endsWith($file, $this->extension)) { + $skip = true; + break; + } + } while (0); + } + } while ($skip); + + /** @noinspection PhpUndefinedVariableInspection */ + + if ($path === false && ! empty($this->queue)) { + list($path, $file) = array_shift($this->queue); + } + + $this->current = $path; + $this->key = $file; + } + + #[\ReturnTypeWillChange] + public function key() + { + return $this->key; + } + + public function valid(): bool + { + return $this->current !== false; + } + + public function rewind(): void + { + if ($this->files === null) { + $files = scandir($this->path); + natcasesort($files); + $this->files = new ArrayIterator($files); + } + $this->files->rewind(); + $this->queue = array(); + $this->next(); + } +} |