Re: RecursiveDirectoryIterator and foreach

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux