...

View Full Version : Read Directory with Class



digital-ether
05-30-2006, 12:53 AM
Its not a directory to array function, so it doesnt chew up resources with a large array of directory elements. Instead its a pretty straight forward class that allows you to read through a directory and perform functions in a linear fashion.

All the recursion.. bla bla bla is done by the class instead of having to use a directory to array class with heavy recursion, and then have to recurse throught the array it produces, which is just as complicated.

Please let me know how userful or straight forward or not the class is and what areas need work... :)




/**
* Reads a Directory and executes defined events when each directory element is read
*/
class readDir {

var $path;
var $errtxt;
var $errcount;
var $recurse;
var $events;
var $handlers;

/**
* Constructor (executed when we instatiate the class)
*/
function readDir() {
$this->recursive = false;
$this->errcount = 0;
$this->events = array('readDir_dir', 'readDir_file');
$this->handlers = array();
}

/**
* Set the directory to read
* @param string full directory path
*/
function setPath( $path ) {
if (!is_dir($path)) {
$this->_error('The supplied argument, '.$path.', is not a valid directory path!');
return false;
}
$this->path = $path;
return true;
}

/**
* Set and event handler
* @param string event name
* @param string event handler function name
*/
function setEvent( $event, $handler ) {
if (in_array($event, $this->events) !== false) {
$this->handlers[$event] = $handler;
} else {
$this->_error('Event Type specified does not exist.');
return false;
}
return true;
}

/**
* Set if we want to read through sub folders recursively
* @param bool TRUE or FALSE
*/
function readRecursive( $bool = true ) {
$this->recurse = $bool;
}

/**
* Read the directory
*/
function read() {
if ( !is_dir($this->path) ) {
$this->_error('Directory to read from is invalid. Please use setPath() to defind a valid directory.');
return false;
}

// all set, start reading
return $this->_read($this->path);
}

function _read($dir) {
if ($dh = opendir($dir)) {
$i = 0;
while ($el = readdir($dh)) {
$path = $dir.'/'.$el;

if (is_dir($path) && $el != '.' && $el != '..') {
if ($this->_trigger('readDir_dir', $path, $el) == -1) {
closedir($dh);
return true;
}

if ($this->recurse) { // read sub directories recursively
_read($path);
}
} elseif (is_file($path)) {
if ($this->_trigger('readDir_file', $path, $el) == -1) {
closedir($dh);
return true;
}
}
$i++;
}
closedir($dh);
return true;
} else {
$this->_error('Could not open the directory, '.$path);
}
return false;
}

function _trigger($event, $path, $el) {
if ($this->handlers[$event]) {
if (!function_exists($this->handlers[$event])) {
$this->_error('User Function, '.$this->handlers[$event].', defined for the event, '.$event.', does not exist');
return false;
}
return call_user_func($this->handlers[$event], $path, $el);
}
}

function _error($txt) {
$this->errcount++;
$this->errtxt = $txt;
}

/**
* View the last error logged
*/
function error() {
return $this->errtxt;
}

/**
* View the last error number
*/
function errorCount() {
return $this->errcount;
}

}


Usage:



/**
* Usage of the readDir class
*/

$base_dir = dirname(__FILE__); // the directory this script is in
$dir = new readDir(); // instantiate our class

// set the directory to read
if (!$dir->setPath( $base_dir.'/dir1' )) {
die($dir->error());
}
// set recursive reading of sub folders
$dir->readRecursive(true);
// set a function to call when a new dir is read
if (!$dir->setEvent( 'readDir_dir', 'my_dir_function' )) { ;
die($dir->error());
}
// set a function to call when a new file is read
if (!$dir->setEvent( 'readDir_file', 'my_file_function' )) {
die($dir->error());
}
// read the dir
if ( !$dir->read() ) {
die($dir->error());
}

// our custom function called when a new dir is read
function my_dir_function($path, $filename) {
echo 'Reading Dir: '.$path.'<br />';
}

// our custom function called when a new file is read
function my_file_function($path, $filename) {
echo 'Reading File: '.$path.'<br />';
if (preg_match("/\.php$/i", $filename)) {
echo 'This is a PHP File.<br />';
}

if ($filename == 'secret_php_file.php') {
echo 'We found the file we are looking for. Stopping directory read.<br />';
return -1; // return negative 1 to stop the reading of the directory
}
}



Everything is straight forward maybe except for the setEvent() function. This allows you to define a custom function to be called when the class reaches a directory element, such as a file or folder.

It takes to params:

The event name, either:
1) readDir_dir - triggered when a directory is read
2) readDir_file - triggered when a file is read

and the custom function name.

Each event then calls your custom function passing it two params:

1) $path - the full pathname of the dir or file
2) $filename - the filename of the dir or file

You can use the $path param with regular file functions like filesize(), fileatime(), fopen() and fread(), delete() to perform the tasks you want on the files or directories.


:thumbsup:

--
added ability to stop directory read by returning -1 in your custom functions

timgolding
04-12-2009, 05:45 PM
You class has one error it is


if ($this->recurse) { // read sub directories recursively
_read($path);
}


Gives this error:

Call to undefined function _read...

Here's the fix


if ($this->recurse) { // read sub directories recursively
$this->_read($path);
}


Now it works perfectly. So thanks digital-ether



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum