Location: PHPKode > scripts > SPL and Iterators > spl-and-iterators/smartdir/class.oSmartDir.php
<?php
/**
 * smartDir package
 * @author Johan Barbier <hide@address.com>
 * @version 20011120
 */

/**
 * class myFilter
 * check active filters
 * RecursiveFilterIterator child
 */
class myFilter extends RecursiveFilterIterator {

	/**
	 * active filter ON (keep these)
	 *
	 * @var mixed
	 */
	private $mFilterOn;

	 /**
	 * active filter OFF (do not keep these)
	 *
	 * @var mixed
	 */
	private $mFilterOff;

	 /**
	 * iterator
	 *
	 * @var iterator
	 */
	private $it = null;

	 /**
	 * error message
	 *
	 * @var string
	 */
	const ERROR_NO_VALID_FILTER = '{__FILTER__} is not a valid setable filter';

	/**
	 * Constructor
	 *
	 * @param iterator $it
	 * @param mixed $mFilterOn
	 * @param mixed $mFilterOff
	 */
	public function __construct ($it, $mFilterOn, $mFilterOff) {
		parent::__construct ($it);
		$this -> it = $it;
		$this -> mFilterOn = $mFilterOn;
		$this -> mFilterOff = $mFilterOff;
	}

	/**
	 * Function accept ()
	 * returns true or false if the current element is accepted or not
	 *
	 * @return boolean
	 */
	public function accept () {
     	if (!is_null ($this -> mFilterOn)) {
    		if (!is_array ($this -> mFilterOn)) {
    			$mPos = strpos ($this -> it -> getFileName (), (string)$this -> mFilterOn);
    			if (false === $mPos) {
    				return false;
    			}
    		} else {
	    		foreach ($this -> mFilterOn as $sFilter) {
	    			$mPos = strpos ($this -> it -> getFileName (), (string)$sFilter);
	    			if (false !== $mPos) {
	    				return true;
	    			}
	    		}
	    		return false;
    		}
    	}
    	if (!is_null ($this -> mFilterOff)) {
    		if (!is_array ($this -> mFilterOff)) {
    			$mPos = strpos ($this -> it -> getFileName (), (string)$this -> mFilterOff);
    			if (false !== $mPos) {
    				return false;
    			}
    		} else {
	    		foreach ($this -> mFilterOff as $sFilter) {
	    			$mPos = strpos ($this -> it -> getFileName (), (string)$sFilter);
	    			if (false !== $mPos) {
	    				return false;
	    			} else {
	    				return true;
	    			}
	    		}
	    		return false;
    		}
    	}
    	return true;
	}
}

/**
 * Class MyRecursiveDirectoryIterator
 * parent of main class, RecursiveDirectoryIterator child
 *
 */
class MyRecursiveDirectoryIterator extends RecursiveDirectoryIterator {

	/**
	 * are dir valid
	 *
	 * @var boolean
	 */
	protected $bDir = true;

	/**
	 * are files valid
	 *
	 * @var boolean
	 */
	protected $bFile = true;

	/**
	 * filter ON (keep these)
	 *
	 * @var mixed
	 */
	protected $mFilterOn = null;

	/**
	 * filter OFF (do not keep these)
	 *
	 * @var mixed
	 */
	protected $mFilterOff = null;

	/**
	 * Recursive dir or not
	 *
	 * @var boolean
	 */
	protected $bRecurse = true;

	/**
	 * props that can be set
	 *
	 * @var array
	 */
	protected $aCanBeSet = array (
	'FLAG',
	'FILTER_ON',
	'FILTER_OFF',
	'DIR',
	'FILE',
	'PATH',
	'RECURSE'

	);
	/**
	 * filter ON (keep these)
	 *
	 * @var RecursiveDirectoryIterator class constant
	 */
	protected $cFlag = 0;

	/**
	 * path to be read
	 *
	 * @var string (valid path)
	 */
	protected $sPath;

	protected $sCreatedDir = null;

	 /**
	 * error messages
	 *
	 * @var string
	 */
	const ERROR_PATH_NOT_FOUND = '{__PATH__} has not been found';
	const ERROR_PROP_NOT_SETABLE = '{__PROP__} is not a setable property';
	const ERROR_BAD_PROP_VALUE = '{__VAL__} is not a correct value for {__PROP__}';
	const ERROR_NO_BOOLEAN = '{__PROP__} value must be a boolean';

	/**
	 * getChildren will retrieve sub path
	 *
	 * @return subiterator
	 */
	public function getChildren () {
		$iSub =  new self ($this -> getPathname ());
		$iSub -> bDir = $this -> bDir;
		$iSub -> bFile = $this -> bFile;
		$iSub -> mFilterOn = $this -> mFilterOn;
		$iSub -> mFilterOff = $this -> mFilterOff;
		return $iSub;
	}

	/**
	 * get current key
	 *
	 * @return string
	 */
    public function key () {
        return $this -> getPath ();
    }

    /**
	 * get current file
	 *
	 * @return string
	 */
    public function current () {
    	return $this -> getFileName ();
    }

    /**
     * is the current element valid or not
     *
     * @return boolean
     */
  	public function valid () {
  		if (!is_null ($this -> sCreatedDir)) {
  			if ($this -> current () === $this -> sCreatedDir) {
  				return false;
  			}
  		}
  		$oFilter = new myFilter ($this, $this -> mFilterOn, $this -> mFilterOff);
		if (true === parent::valid ()) {
			if (false === $oFilter -> accept ()) {
				if (false === $this -> isDir ()) {
					parent::next ();
					return $this -> valid ();
				} else {
					return true;
				}
			}
	    	if (false === $this -> bDir) {
	    		if (true === $this -> isDir ()) {
		    		parent::next ();
		    		return $this -> valid ();
	    		}
	    	}
	    	if (false === $this -> bFile) {
	    		if (true === $this -> isFile ()) {
		    		parent::next ();
		    		return $this -> valid ();
	    		}
	    	}
			return true;
		}
		return false;
    }

    /**
     * Setter
     *
     * @param string $sProp
     * @param mixed $mVal
     */
	public function __set ($sProp, $mVal) {
		if (!in_array ($sProp, $this -> aCanBeSet)) {
			throw new Exception (str_replace ('{__PATH__}', $sProp, self::ERROR_PROP_NOT_SETABLE));
		}
		switch ($sProp) {
			case 'FLAG' :
				if (!in_array ($mVal, array (parent::CURRENT_AS_FILEINFO, parent::KEY_AS_FILENAME, parent::NEW_CURRENT_AND_KEY, 0))) {
					throw new Exception (str_replace (array ('{__VAL__}', '{__PROP__}'), array ($mVal, $sProp), self::ERROR_PATH_NOT_FOUND));
				}
				$this -> cFlag = $mVal;
				break;
			case 'FILTER_ON' :
				$this -> mFilterOn = $mVal;
				$this -> mFilterOff = null;
				break;
			case 'FILTER_OFF' :
				$this -> mFilterOff = $mVal;
				$this -> mFilterOn = null;
				break;
			case 'DIR' :
				if (!is_bool ($mVal)) {
					throw new Exception (str_replace ('{__PROP__}', $sProp, self::ERROR_NO_BOOLEAN));
				}
				$this -> bDir = $mVal;
				break;
			case 'FILE' :
				if (!is_bool ($mVal)) {
					throw new Exception (str_replace ('{__PROP__}', $sProp, self::ERROR_NO_BOOLEAN));
				}
				$this -> bFile = $mVal;
				break;
			case 'RECURSE' :
				if (!is_bool ($mVal)) {
					throw new Exception (str_replace ('{__PROP__}', $sProp, self::ERROR_NO_BOOLEAN));
				}
				$this -> bRecurse = $mVal;
				break;
			case 'PATH' :
				if (!is_dir ($mVal)) {
					throw new Exception (str_replace ('{__PATH__}', $mVal, self::ERROR_PATH_NOT_FOUND));
				}
				$this -> sPath = $mVal;
				break;
		}
	}
}

/**
 * Class oSmartDir
 * MyRecursiveDirectoryIterator child
 *
 */
class oSmartDir extends MyRecursiveDirectoryIterator {

	/**
	 * Constructor
	 *
	 * @param string $sPath (valid path)
	 */

	const ERROR_COPY_FAILED = 'Failed to copy {__FROM__} to {__TO__}';

	public function __construct ($sPath) {
		if (!is_dir ($sPath)) {
			throw new Exception (str_replace ('{__PATH__}', $sPath, self::ERROR_PATH_NOT_FOUND));
		}
		$this -> sPath = $sPath;
	}

	/**
	 * getDir will retrieve the asked directory
	 *
	 * @return iterator
	 */
	public function getDir () {
		parent::__construct ($this -> sPath, $this -> cFlag);
		if (true === $this -> bRecurse) {
			return new RecursiveIteratorIterator ($this, true);
		} else {
			return $this;
		}
	}

	public function copy ($sTo) {
		$aDir = $this -> getDir ();
		if (!is_dir ($sTo)) {
			mkdir ($sTo, '0755');
		}
		$this -> sCreatedDir = $sTo;
		while ($aDir -> valid ()) {
			if ($aDir -> current () !== $sTo && !$aDir -> isDot ()) {
				if (!$aDir -> isDir ()) {
					if (!@copy ($aDir -> getPathName (), $sTo.'/'.$aDir -> getPathName ())) {
						throw new Exception (str_replace (array ('{__FROM__}', '{__TO__}'), array ($aDir -> getPathName (), $sTo.'/'.$aDir -> getPathName ()), self::ERROR_COPY_FAILED));
					}
				} else {
					if (!@mkdir ($sTo.'/'.$aDir -> getPathName (), '0755')) {
						throw new Exception (str_replace (array ('{__FROM__}', '{__TO__}'), array ($aDir -> getPathName (), $sTo.'/'.$aDir -> getPathName ()), self::ERROR_COPY_FAILED));
					}
				}
			}
			$aDir -> next ();
		}
		$this -> sCreatedDir = null;
	}
}


/**
 * STARTING EXAMPLES
 */
try {
	$oDir = new oSmartDir ('.');
} catch (Exception $e) {
	echo $e -> getMessage ();
}
try {

	echo '<br /><strong>ALL NO RECURSIVE</strong><br />';
	$oDir -> RECURSE = false; // no recursivity
	$aDir = $oDir -> getDir ();
	while ($aDir -> valid ()) {
		if ($aDir -> isDot ()) {
			$aDir -> next ();
		}
		$sHtml = '';
		if ($aDir -> isDir ()) {
			$sHtml.= '<strong>'.$aDir -> current ().'</strong>';
		} else {
			$sHtml.= '<em>'.$aDir -> current ().'</em>';
		}
		$sHtml .= '<br />';
		echo $sHtml;
		$aDir -> next ();
	}

	echo '<br /><strong>ALL</strong><br />';
	$oDir -> RECURSE = true; // recursivity back to true
	$aDir = $oDir -> getDir ();
	while ($aDir -> valid ()) {
		if ($aDir -> isDot ()) {
			$aDir -> next ();
		}
		$sHtml = str_repeat ('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;', $aDir -> getDepth ());
		if ($aDir -> isDir ()) {
			$sHtml.= '<strong>'.$aDir -> current ().'</strong>';
		} else {
			$sHtml.= '<em>'.$aDir -> current ().'</em>';
		}
		$sHtml .= '<br />';
		echo $sHtml;
		$aDir -> next ();
	}

	echo '<br /><strong>ALL + fileSize</strong><br />';
	$oDir -> RECURSE = true; // recursivity back to true
	$aDir = $oDir -> getDir ();
	while ($aDir -> valid ()) {
		if ($aDir -> isDot ()) {
			$aDir -> next ();
		}
		$sHtml = str_repeat ('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;', $aDir -> getDepth ());
		if ($aDir -> isDir ()) {
			$sHtml.= '<strong>'.$aDir -> current ().'</strong>';
		} else {
			$sHtml.= '<em>'.$aDir -> current ().' '.round (($aDir -> getSize()/1024), 2).' Ko</em>';
		}
		$sHtml .= '<br />';
		echo $sHtml;
		$aDir -> next ();
	}

	echo '<br /><strong>ALL</strong><br />';
	$aDir = $oDir -> getDir ();
	foreach ($aDir as $sK => $sV) {
		echo str_repeat ('-----', $aDir -> getDepth()), $sK, ' => ', $sV, '<br />';
	}

	echo '<br /><strong>FILTRE ON SUR PHP</strong><br />';
	$oDir -> FILTER_ON = 'php'; // only shows files with "php" in them
	$aDir = $oDir -> getDir ();
	foreach ($aDir as $sK => $sV) {
		echo str_repeat ('-----', $aDir -> getDepth()), $sK, ' => ', $sV, '<br />';
	}

	echo '<br /><strong>DIR = FALSE</strong><br />';
	$oDir -> DIR = false; // No directory
	$oDir -> FILTER_ON = null; // no filter ON
	$aDir = $oDir -> getDir ();
	foreach ($aDir as $sK => $sV) {
		echo str_repeat ('-----', $aDir -> getDepth()), $sK, ' => ', $sV, '<br />';
	}

	echo '<br /><strong>FILE = FALSE</strong><br />';
	$oDir -> DIR = true; // show directories
	$oDir -> FILE = false; // No files
	$aDir = $oDir -> getDir ();
	foreach ($aDir as $sK => $sV) {
		echo str_repeat ('-----', $aDir -> getDepth()), $sK, ' => ', $sV, '<br />';
	}

	echo '<br /><strong>PATH = bla ET FILTRE OFF SUR PHP</strong><br />';
	$oDir -> PATH = 'bla'; // parth = 'bla'
	$oDir -> FILE = true; // show files
	$oDir -> FILTER_OFF = 'php'; // do not show files with "php" in them
	$aDir = $oDir -> getDir ();
	foreach ($aDir as $sK => $sV) {
		//echo $sK, ' => ', $sV, '<br />';
		echo str_repeat ('-----', $aDir -> getDepth()), $sK, ' => ', $sV, '<br />';
	}

	/**
	 * Create a copy of the whole directory recursively, but ONLY copy files with php in them ;-)
	 */
	$oDir -> FILTER_ON = 'php';
	$oDir -> PATH = '.';
	$oDir -> copy ('copie');

} catch (Exception $e) {
	echo $e -> getMessage (), ' => ', $e -> getLine ();
}
?>
Return current item: SPL and Iterators