Philip Graham wrote:
Here's a RecursiveDirectoryIterator class I've written and find quite useful:
<?php
/**
* This class encapsulates an iterator that iterates over all the files in a
* directory recursively. Only files that don't begin with a '.' are included
* in this iteration. This class essentially wraps an SPL DirectoryIterator
* object and returns each file in the iteration as an SplFileInfo.
*
* @author <a href="mailto:philip@xxxxxxxxxxxx">Philip Graham</a>
*/
class Util_RecursiveFileIterator implements Iterator {
CONST SHOW_DOT_FILES = true;
private $_basePath;
private $_curDirIter;
private $_dirStack;
private $_showDots;
/**
* Constructor. By default the iteration will skip any files that begin
* with a '.' character but this can be changed by passing the class
* constant SHOW_DOT_FILES as the second parameter.
*
* @param string $basePath - The base path of the directory to iterate
over
* @param boolean $showDots - Whether or not to include files that begin
* with a '.' character in the iteration.
*/
public function __construct($basePath, $showDots = false) {
// PREPARE ... THE ... HUMANOID
if(!is_dir($basePath)) {
$basePath = dirname($basePath);
}
if(!$basePath) {
$basePath = '.';
}
// If the given path is relative this function will transform it
// into an equivalent path. This call assumes that the relative path
// is relative to the file that created this iterator.
$this->_basePath = Util_File::getAbsolutePath($basePath, 2);
$this->_showDots = $showDots;
}
/**
* Returns the current value of the iteration
*
* @return FileInfoInfo
*/
public function current() {
return $this->_curDirIter->current();
}
/**
* Returns the index of the current entry.
*
* @return string
*/
public function key() {
$curPath = $this->_curDirIter->getPathname();
$relativeToBase = substr($curPath, strlen($this->_basePath));
return $relativeToBase;
}
/**
* Moves the directory iterator to the next element of the iteration.
*/
public function next() {
$this->_curDirIter->next();
$good = false;
while(!$good) {
if(!$this->_curDirIter->valid()) {
if(count($this->_dirStack) == 0) {
$good = true;
} else {
$this->_curDirIter = array_pop($this->_dirStack);
}
} else if($this->_curDirIter->isDot()) {
if(!$this->_showDots) {
$this->_curDirIter->next();
} else {
$good = true;
}
} else if(!$this->_showDots &&
substr($this->_curDirIter->getFileName(), 0, 1) == '.') {
$this->_curDirIter->next();
} else if($this->_curDirIter->isDir()) {
// Create a new iterator for the sub-dir
$newIter = new DirectoryIterator(
$this->_curDirIter->getPathname());
// Make sure the current iterator is ready to go when it
// gets popped off the stack
$this->_curDirIter->next();
// Push it... push it real good
array_push($this->_dirStack, $this->_curDirIter);
// Set the new iterator
$this->_curDirIter = $newIter;
} else {
$good = true;
}
}
}
/**
* Resets the iterator to first file in the object's base path.
*/
public function rewind() {
$this->_curDirIter = new DirectoryIterator($this->_basePath);
$this->_dirStack = array();
if(!$this->_showDots && $this->_curDirIter->isDot()) {
$this->next();
}
}
/**
* Returns a boolean indicating wether or not there are anymore elements
left
* in the iteration.
*/
public function valid() {
return $this->_curDirIter->valid();
}
}
Usage:
$dirIter = new Util_RecursiveFileIterator('/path/to/directory');
foreach($dirIter AS $fileName => $fileInfo) {
// $fileName is the basename of the file and $fileInfo is a SplFileInfo
// for the file
}
Hope this helps!
Hi, although I don't think this will work in my situation, there is an
interesting piece of code that you have.
array_push($this->_dirStack, $this->_curDirIter);
Are you able to "inject" the iterator with more items? I would like to
do this with the RecursiveDirectoryIterator where-by I "inject" fake
files into the iterator. Is this what you're doing here?
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php