Location: PHPKode > scripts > Folder Stats > folder-stats/FolderStats.class.php
<?php // 4
/**
* This class gets information inside a folder and its subfolders.
* With few steps you can read:
* 	- total size of folder [ ->getSize() ]
*       - folder and subfolders info [ ->getDetails() or ->getTree() ]
*       - all files info [ ->getDetails() or ->getTree() ]
*       - a valid W3C XML rappresentation of the folder and its subfolder
*         with files informations [ ->getXML() ]
*       - a Flash optimized XML rappresentation of the folder and its subfolder
*         with files informations [ ->getFlashXML() ]
*       - size of a file [ self::readableSize ]
*       - file or folder permissions [ self::getPerms ]
* ______________________________________________________________
* EXAMPLE:
*			$FS = &new FolderStats('./');
*                       var_dump( $FS->getSize() );
* --------------------------------------------------------------
* @Compatibility	>= PHP 4
* @Author		Andrea Giammarchi
* @Site			http://www.devpro.it/
* @Mail			andrea [ at ] 3site [ dot ] it
* @Date			03/03/2005
* @LastModified		12/07/2005 10:50
* @Version		1.0 tested
*/
class FolderStats {
	
	/**
	* 'Private' variables:
	*	__size:Array		Integer size and readable size of the folder
        *       __stats:Array		Files and folders informations container
        *       __folder:String		Folder to parse
        *       __XML:String		Valid W3C XML or Flash optimized XML rappresentation
	*/
	var $__size;
	var $__stats;
	var $__folder;
	var $__XML;
	
	/**
	* Public constructor:
	*	Initializes private variables and start loop inside folder.
        *       	new FolderStats( $folder:String )
	* @Param	String		folder to parse recoursively
        * 				[ DEFAULT: current directory ]
	*/
	function FolderStats( $folder = './' ) {
		if(substr($folder, -1) !== '/' && substr($folder, -1) !== '\\')
			$folder .= '/';
		$this->__folder = &$folder;
		$this->__stats = Array();
		$this->__XML = Array();
		$this->__stats['files'] = Array();
		$this->__stats['folders'] = Array();
		$this->__size = &$this->__folderInfo( $this->__folder );
	}
	
	/**
	* Public method:
	*	returns an anrray with 2 keys and 2 values
        *       	this->getSize():Array
        * @Return	Array		An array with 2 keys;
        * 				'size' => (int) integer size
        *                               'rsize' => (string) readable size (i.e. '156.40 Kb')
	*/
	function getSize() {
		return Array(
			'size'=>$this->__size,
			'rsize'=>FolderStats::readableSize( $this->__size )
		);
	}
	
	/**
	* Public method:
	*	returns an anrray with all information for each file and each folder
        *       	this->getDetails():Array
        * @Return	Array		An array with all details
	*/
	function getDetails() {
		return $this->__stats;
	}
	
	/**
	* Public method:
	*	returns a string with an optimized and Flash dedicated rappresentation
        *       of the folder and its files or subfolders.
        *       	this->getFlashXML():String
        * @Return	String		formatted XML string
	*/
	function getFlashXML() {
		$XML = $this->__xmlFlashLooper( $this->__XML );
		return str_replace( 'name', 'label', $XML );
	}
	
	/**
	* Public method:
	*	returns a string with a valid W3C XML rappresentation
        *       of the folder and its files or subfolders.
        *       	this->getXML():String
        * @Return	String		formatted XML string
	*/
	function getXML() {
		$XML = "<?xml version=\"1.0\"?>
<!DOCTYPE directory [
	<!ELEMENT directory	(name,(directory|file)*)>
	<!ELEMENT file		(name,size,rsize,cdate,mdate,perms)>
	<!ELEMENT name		(#PCDATA)>
	<!ELEMENT size		(#PCDATA)>
	<!ELEMENT rsize		(#PCDATA)>
	<!ELEMENT cdate		(#PCDATA)>
	<!ELEMENT mdate		(#PCDATA)>
	<!ELEMENT perms		(#PCDATA)>
]>".$this->__xmlLooper( $this->__XML );
		return $XML;
	}
	
	/**
	* Public method:
	*	returns an array with indented informations folder by folder
        *       	this->getTree():Array
        * @Return	Array		An array with indented informations of eah subfolder and its files
	*/
	function getTree() {
		$__tree = Array();
		$__folder = preg_replace( "/^([^\a]+?)(\/)?$/i", "\\1", $this->__folder );
		$__tree[$__folder] = $this->__findFileInFolder( $__folder );
		for( $a = 0, $b = &count( $this->__stats['folders'] ); $a < $b; $a++ )
			$__tree[$this->__stats['folders'][$a]['name']] =
			$this->__findFileInFolder( $this->__stats['folders'][$a]['name'] );
		return $__tree;
	}
	
	/**
	* 'Static' Public method:
	*	returns a readable rappresentation of an integer size
        *       	FolderStats::readableSize($size:Integer, $decimals:Integer):String
        * @Param	Integer		Integer size to convert in readable size
        * @Param	Integer		how many number as decimal values ( something like %.N for float numbers )
        * 				[Default: 2]
        * @Return	String		A readable rappresentation of this size
	*/
	function readableSize( $size, $dec = 2 ) {
		// Original function name: fSize [ www.devpro.it ]
		// Converts filesize in Kb, Mb, Gb or Tb [ Zb as incredible size ! ]
		// andr3a [ www.3site.it ] 23 / 10 / 2004
		// EXAMPLE:
		//		echo FolderStats::readableSize( 87983598 );
                //		// will print 83.91 Mb
		$toEval = '';
		$type = Array( 'bytes', 'Kb', 'Mb', 'Gb', 'Tb', 'Zb' );
		$nsize = ( $size = (int) $size );
		$times = 0;
		while( $nsize >= 1024 ) {
			$nsize = $nsize / 1024;
			$toEval .= ' / 1024';
			$times++;
		}
		if( $times === 0 )
			$fSize = $size.' '.$type[$times];
		else {
			eval( '$size = ( $size'.$toEval.' );' );
			$fSize =  number_format( $size, $dec, '.', '' ).' '.$type[$times];
		}
		return $fSize;
	}
	
	/**
	* 'Static' Public method:
	*	returns a readable rappresentation of a file or folder permissions
        *       	FolderStats::getPerms($perms:fileperms()):String
        * @Param	fileperms()	fileperms returned value for a file or folder [i.e. fileperms('./folder')]
        * @Return	String		A readable rappresentation of this permissions
	*/
	function getPerms( $perms ) {
		// Original code from WWW.PHP.NET
                // [ http://uk.php.net/manual/en/function.fileperms.php ]
		// Checks filepermissions and returns a readable rappresentation
		// EXAMPLE:
		//		echo FolderStats::getPerms( fileperms( './FOLDER' ) );
                //		// will print for example "drwxrwxrwx" if has a chomd 777
		
		if( ( $perms & 0xC000 ) == 0xC000 )
			$info = 's';						// Socket
		elseif( ( $perms & 0xA000 ) == 0xA000 )
			$info = 'l';						// Symbolic Link
		elseif( ( $perms & 0x8000 ) == 0x8000 )
			$info = '-';						// Regular
		elseif( ( $perms & 0x6000 ) == 0x6000 )
			$info = 'b';						// Block special
		elseif( ( $perms & 0x4000 ) == 0x4000 )
			$info = 'd';						// Directory
		elseif( ( $perms & 0x2000 ) == 0x2000 )
			$info = 'c';						// Character special
		elseif( ( $perms & 0x1000 ) == 0x1000 )
			$info = 'p';						// FIFO pipe
		else
			$info = 'u';						// Unknown
		
		// Owner
		$info .= ( ( $perms & 0x0100 ) ? 'r' : '-' );
		$info .= ( ( $perms & 0x0080 ) ? 'w' : '-' );
		$info .= ( ( $perms & 0x0040 ) ?
			( ( $perms & 0x0800 ) ? 's' : 'x' ) : ( ( $perms & 0x0800 ) ? 'S' : '-' ) );
			
		// Group
		$info .= ( ( $perms & 0x0020 ) ? 'r' : '-' );
		$info .= ( ( $perms & 0x0010 ) ? 'w' : '-' );
		$info .= ( ( $perms & 0x0008 ) ?
			( ( $perms & 0x0400 ) ? 's' : 'x' ) : ( ( $perms & 0x0400 ) ? 'S' : '-' ) );
			
		// World
		$info .= ( ( $perms & 0x0004 ) ? 'r' : '-' );
		$info .= ( ( $perms & 0x0002 ) ? 'w' : '-' );
		$info .= ( ( $perms & 0x0001 ) ?
			( ( $perms & 0x0200 ) ? 't' : 'x' ) : ( ( $perms & 0x0200 ) ? 'T' : '-' ) );
			
		return $info;
	}
	
	/**
	* 'Private' methods
	*/
	function __findFileInFolder( $folder ) {
		$__f = Array();
		for( $a = 0, $b = &count( $this->__stats['files'] ); $a < $b; $a++ ) {
			$__g = explode( '/', $this->__stats['files'][$a]['name'] );
			if( ( $c = ( count( $__g ) - 1 ) ) > 0 ) {
				$__l = $__g[$c];
				unset( $__g[$c] );
			}
			$__g = implode( '/', $__g );
			if( $__g == $folder )
				array_push( $__f, Array(
						'name'=>$__l,
						'size'=>$this->__stats['files'][$a]['size'],
						'rsize'=>$this->__stats['files'][$a]['rsize'],
						'cdate'=>$this->__stats['files'][$a]['cdate'],
						'mdate'=>$this->__stats['files'][$a]['mdate'],
						'perms'=>$this->__stats['files'][$a]['perms']
					)
				);
		}
		return $__f;
	}
	function __xmlFlashLooper( $ar, $level = 0 ) {
		$__XML = "";
		while( list( $k, ) = each( $ar ) ) {
			if( is_int( $k ) ) {
				$__XML .= "\n".str_repeat( "\t", $level )."<node ";
				foreach( $ar[$k] as $kk => $vv )
					$__XML .= "{$kk}=\"{$vv}\" ";
				$__XML .= "/>";
			}
			else {
				if( $k != '' && $k != '.' ) {
					$__XML .= "\n".str_repeat( "\t", $level )."<node label=\"{$k}\">";
					$__XML .= $this->__xmlFlashLooper( $ar[$k], ( $level + 1 ) );
					$__XML .= "\n".str_repeat( "\t", $level )."</node>";
				}
				else
					$__XML .= $this->__xmlFlashLooper( $ar[$k], $level );
			}
		}
		return $__XML;
	}
	function __xmlLooper( $ar, $level = 0 ) {
		$__XML = "";
		while( list( $k, ) = each( $ar ) ) {
			if( is_int( $k ) ) {
				$__XML .= "\n".str_repeat( "\t", $level )."<file>";
				foreach( $ar[$k] as $kk => $vv )
					$__XML .= "\n".str_repeat( "\t", $level + 1 )."<{$kk}>{$vv}</{$kk}>";
				$__XML .= "\n".str_repeat( "\t", $level )."</file>";
			}
			else {
				if( $k != '' && $k != '.' ) {
					$__XML .= "\n".str_repeat( "\t", $level )."<directory>";
					$__XML .= "\n".str_repeat( "\t", $level + 1 )."<name>{$k}</name>";
					$__XML .= $this->__xmlLooper( $ar[$k], ( $level + 1 ) );
					$__XML .= "\n".str_repeat( "\t", $level )."</directory>";
				}
				else {
					$__XML .= $this->__xmlLooper( $ar[$k], $level );
				}
			}
		}
		return $__XML;
	}
	final private function __folderInfo( $folder ) {
		$totalbytes = 0;
		if( $handle = opendir( $folder ) ) {
			while( false !== ( $file = readdir( $handle ) ) ) {
				if( $file != '.' && $file != '..' && is_dir( $folder.$file ) == false ) {
					$__ns = filesize( $folder.$file );
					$information = Array(
						'name'=>$folder.$file,
						'size'=>$__ns,
						'rsize'=>self::readableSize( $__ns ),
						'cdate'=>date( 'Y-m-d H:i:s', @filectime( $folder.$file ) ),
						'mdate'=>date( 'Y-m-d H:i:s', @filemtime( $folder.$file ) ),
						'perms'=>self::getPerms( fileperms( $folder.$file ) )
					);
					array_push( $this->__stats['files'], $information );
					$__toXML = explode( '/', $folder );
					$__indexXML = '';
					for( $a = 0, $b = ( count( $__toXML ) - 1 ); $a < $b; $a++ )
						$__indexXML .= '[\''.$__toXML[$a].'\']';
					$information['name'] = basename( $information['name'] );
					eval( 'if( isSet( $this->__XML'.$__indexXML.' ) == false ) { $this->__XML'.$__indexXML.' = Array(); }' );
					eval( 'array_push( $this->__XML'.$__indexXML.', $information );' );
					$totalbytes += $__ns;
				}
				elseif( $file != '.' && $file != '..' && is_dir( $folder.$file ) == true ) {
					$__toXML = explode( '/', $folder.$file );
					$__indexXML = '';
					for( $a = 0, $b = &count( $__toXML ); $a < $b; $a++ )
						$__indexXML .= '[\''.$__toXML[$a].'\']';
					eval( '$this->__XML'.$__indexXML.' = Array();' );
					array_push( $this->__stats['folders'], Array(
						'name'=>$folder.$file,
						'cdate'=>date( 'Y-m-d H:i:s', @filectime( $folder.$file ) ),
						'mdate'=>date( 'Y-m-d H:i:s', @filemtime( $folder.$file ) ),
						'perms'=>self::getPerms( fileperms( $folder.$file ) )
						)
					);
					$totalbytes += $this->__folderInfo( $folder.$file.'/' );
				}
			}
			closedir( $handle );
		}
		return $totalbytes;	
	}
}
?>
Return current item: Folder Stats