doc: Iterate files alphabetically and directories last

This commit is contained in:
Eric Lippmann 2016-03-30 15:26:24 +02:00
parent 03e4d626f1
commit 528be1ee79

View File

@ -3,14 +3,22 @@
namespace Icinga\Util; namespace Icinga\Util;
use ArrayIterator;
use InvalidArgumentException; use InvalidArgumentException;
use Iterator; use RecursiveIterator;
/** /**
* Iterator for traversing a directory * Iterator for traversing a directory
*/ */
class DirectoryIterator implements Iterator class DirectoryIterator implements RecursiveIterator
{ {
/**
* Iterate files first
*
* @var int
*/
const FILES_FIRST = 1;
/** /**
* Current directory item * Current directory item
* *
@ -26,11 +34,18 @@ class DirectoryIterator implements Iterator
protected $extension; protected $extension;
/** /**
* Directory handle * Scanned files
* *
* @var resource * @var ArrayIterator
*/ */
private $handle; private $files;
/**
* Iterator flags
*
* @var int
*/
protected $flags;
/** /**
* Current key * Current key
@ -46,6 +61,13 @@ class DirectoryIterator implements Iterator
*/ */
protected $path; protected $path;
/**
* Directory queue if FILES_FIRST flag is set
*
* @var array
*/
private $queue;
/** /**
* Whether to skip empty files * Whether to skip empty files
* *
@ -72,8 +94,9 @@ class DirectoryIterator implements Iterator
* *
* @param string $path The path of the directory to traverse * @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 string $extension The file extension to filter for. A leading dot is optional
* @param int $flags Iterator flags
*/ */
public function __construct($path, $extension = null) public function __construct($path, $extension = null, $flags = null)
{ {
if (empty($path)) { if (empty($path)) {
throw new InvalidArgumentException('The path can\'t be empty'); throw new InvalidArgumentException('The path can\'t be empty');
@ -82,6 +105,9 @@ class DirectoryIterator implements Iterator
if (! empty($extension)) { if (! empty($extension)) {
$this->extension = '.' . ltrim($extension, '.'); $this->extension = '.' . ltrim($extension, '.');
} }
if ($flags !== null) {
$this->flags = $flags;
}
} }
/** /**
@ -96,6 +122,23 @@ class DirectoryIterator implements Iterator
return is_dir($path) && is_readable($path); return is_dir($path) && is_readable($path);
} }
/**
* {@inheritdoc}
*/
public function hasChildren()
{
return static::isReadable($this->current);
}
/**
* {@inheritdoc}
*/
public function getChildren()
{
return new static($this->current, $this->extension, $this->flags);
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -110,12 +153,14 @@ class DirectoryIterator implements Iterator
public function next() public function next()
{ {
do { do {
$file = readdir($this->handle); $this->files->next();
if ($file === false) { $skip = false;
$key = false; if (! $this->files->valid()) {
$file = false;
$path = false;
break; break;
} else { } else {
$skip = false; $file = $this->files->current();
do { do {
if ($this->skipHidden && $file[0] === '.') { if ($this->skipHidden && $file[0] === '.') {
$skip = true; $skip = true;
@ -125,7 +170,10 @@ class DirectoryIterator implements Iterator
$path = $this->path . '/' . $file; $path = $this->path . '/' . $file;
if (is_dir($path)) { if (is_dir($path)) {
$skip = true; if ($this->flags & static::FILES_FIRST === static::FILES_FIRST) {
$this->queue[] = array($path, $file);
$skip = true;
}
break; break;
} }
@ -138,16 +186,18 @@ class DirectoryIterator implements Iterator
$skip = true; $skip = true;
break; break;
} }
$key = $file;
$file = $path;
} while (0); } while (0);
} }
} while ($skip); } while ($skip);
$this->current = $file;
/** @noinspection PhpUndefinedVariableInspection */ /** @noinspection PhpUndefinedVariableInspection */
$this->key = $key;
if ($path === false && ! empty($this->queue)) {
list($path, $file) = array_shift($this->queue);
}
$this->current = $path;
$this->key = $file;
} }
/** /**
@ -171,21 +221,11 @@ class DirectoryIterator implements Iterator
*/ */
public function rewind() public function rewind()
{ {
if ($this->handle === null) { if ($this->files === null) {
$this->handle = opendir($this->path); $this->files = new ArrayIterator(scandir($this->path));
} else {
rewinddir($this->handle);
} }
$this->files->rewind();
$this->queue = array();
$this->next(); $this->next();
} }
/**
* Close directory handle if created
*/
public function __destruct()
{
if ($this->handle !== null) {
closedir($this->handle);
}
}
} }