<?php
    
Class DirectoryList {
        public 
$path "";
        public 
$size 0;
        public 
$fileCount 0;
        public 
$directoryCount 0;
        public 
$itemCount 0;
        
        public 
$files = array();
        public 
$directories = array();
        
        public 
$messageFormat "\n";
        
        public function 
__construct($path false) {
            if (!
$path) throw new Exception('No path specified');
            if (!
file_exists($path)) throw new Exception('Specified path doesn\'t exist.');
            if (
filetype($path) != 'dir') throw new Exception('Path is not a directory.');
            if (
substr($path, -1) != '/') {
                
$path .= '/';
            }
            
$this->path $path;
            
$this->readDirectory();
        }
        
        private function 
readDirectory() {
            
$cdir getcwd();
            if (!
chdir($this->path)) throw new Exception('Unable to change to directory ' $this->path);
            if (!
$files glob('*')) throw new Exception('Unable to read directory ' $this->path);
            
$exceptions = array();
            foreach (
$files as $file) {
                if (
$file{0} != '.') {
                    
$this->itemCount ++;
                    try {
                        if (!
$filetype filetype($this->path $file)) throw new Exception('Unable to stat filetype for ' $file);
                        if (
$filetype == 'dir') {
                            
$this->directories[] = $this->getDirDetails($file);
                            
$this->directoryCount ++;
                        } else {
                            
$this->files[] = $this->getFileDetails($file);
                            
$this->fileCount ++;
                        }
                    } catch (
Exception $e) {
                        
$exceptions[] = $e->getMessage();
                    }
                }
            }
            if (
count($exceptions) > 0) {
                throw new 
Exception('The following errors occured during directory reading:'$this->messageFormat implode($this->messageFormat$exceptions));
            }
            
chdir($cdir);
        }
        
        private function 
getFileDetails($file) {
            
$fileDetails = array();
            
$fileDetails['name'] = $file;
            if (!
$fileDetails['size'] = @filesize($this->path $file)) throw new Exception('Unable to stat filesize for ' $this->path $file);
            if (!
$fileDetails['date'] = @filemtime($this->path $file)) throw new Exception('Unable to stat last modified date for ' $this->path $file);
            
$this->size += $fileDetails['size'];
            return 
$fileDetails;
        }
        
        private function 
getDirDetails($dir) {
            
$directoryDetails = array();
            
$directoryDetails['name'] = $dir;
            if (!
$directoryDetails['date'] = @filectime($this->path $file)) throw new Exception('Unable to stat last modified date for ' $this->path $file);
            return 
$directoryDetails;
        }
        
        public function 
formatSize($bytes) {
            if (
$bytes >= 1099511627776) {
                
$return round($bytes 1024 1024 1024 10242);
                
$suffix "TB";
            } elseif (
$bytes >= 1073741824) {
                
$return round($bytes 1024 1024 10242);
                
$suffix "GB";
            } elseif (
$bytes >= 1048576) {
                
$return round($bytes 1024 10242);
                
$suffix "MB";
            } elseif (
$bytes >= 1024) {
                
$return round($bytes 10242);
                
$suffix "KB";
            } else {
                
$return $bytes;
                
$suffix "Byte";
            }
            if (
$return == 1) {
                
$return .= " " $suffix;
            } else {
                
$return .= " " $suffix "s";
            }
            return 
$return;
        }

        public function 
pathToHTML($path$seperator '/') {
            if (
$path == '/') {
                
$return 'Root';
            } else {
                
$patharray explode('/'$path);
                
$c = (count($patharray) - 1);
                
$return '<a class="parent" href="/">Root</a> ' $seperator ' ';
                
$pathvar '/';
                if (
$c 1) {
                    for (
$i 1$i $c$i ++) {
                        
$pathvar .= $patharray[$i] . '/';
                        
$return .= '<a class="parent" href="' $pathvar '">' $patharray[$i] . '</a> ' $seperator ' ';
                    }
                }
                
$return .= $patharray[$c];
            }
            return 
$return;
        }
        
        public function 
sortDirectory($column$direction) {
            if (
$direction != SORT_ASC && $direction != SORT_DESC) throw new Exception('Unknown sorting Direction, expected SORT_ASC or SORT_DESC');
            if (
$this->fileCount 0) {
                
$hasFiles true;
                foreach (
$this->files as $key => $row) {
                    
$fileNames[$key] = $row['name'];
                    
$fileSizes[$key] = $row['size'];
                    
$fileDates[$key] = $row['date'];
                }
                
$lowerFileNames array_map('strtolower'$fileNames);
            }
            if (
$this->directoryCount 0) {
                
$hasDirectories true;
                foreach (
$this->directories as $key => $row) {
                    
$directoryNames[$key] = $row['name'];
                    
$directoryDates[$key] = $row['date'];
                }
                
$lowerDirectoryNames array_map('strtolower'$directoryNames);
            }
            switch(
$column) {
                case 
'name':
                    if (
$hasFiles) {
                        if (!
array_multisort($lowerFileNames$directionSORT_STRING$fileSizesSORT_ASC$fileDatesSORT_ASC$this->files)) throw new Exception('Unable to sort files');
                    }
                    if (
$hasDirectories) {
                        if (!
array_multisort($lowerDirectoryNames$directionSORT_STRING$directoryDatesSORT_ASC$this->directories)) throw new Exception('Unable to sort directories');
                    }
                    break;
                case 
'size':
                    if (
$hasFiles) {
                        if (!
array_multisort($fileSizes$direction$fileNamesSORT_ASCSORT_STRING$fileDatesSORT_ASC$this->files)) throw new Exception('Unable to sort files');
                    }
                    if (
$hasDirectories) {
                        if (!
array_multisort($lowerDirectoryNames$directionSORT_STRING$directoryDatesSORT_ASC$this->directories)) throw new Exception('Unable to sort directories');
                    }
                    break;
                case 
'date':
                    if (
$hasFiles) {
                        if (!
array_multisort($fileDates$direction$fileNamesSORT_ASCSORT_STRING$fileSizesSORT_ASC$this->files)) throw new Exception('Unable to sort files');
                    }
                    if (
$hasDirectories) {
                        if (!
array_multisort($directoryDates$direction$directoryNamesSORT_ASCSORT_STRING$this->directories)) throw new Exception('Unable to sort Directories');
                    }
                    break;
                default:
                    throw new 
Exception('Unknown column selected for sorting.');
            }
        }
    }
?>