Re: RecursiveDirectoryIterator and foreach

From: Date: Mon, 23 Feb 2009 17:32:26 +0000
Subject: Re: RecursiveDirectoryIterator and foreach
References: 1 2  Groups: php.general 
Request: Send a blank email to php-general+get-288690@lists.php.net to get a copy of this message
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@lightbox.org">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?

« previous php.general (#288690) next »