File List [PHP]

Download Source Code

FileList.20191021-213700.zip [Downloads: 60]
SHA1: b07b3271c5e96de2c2513e000edc6a8afc1a081d

The script reads in all subdirectories and files in a given directory, sorts them, and lists them in a HTML table. Files are assigned an icon according to the file type to make it more visually appealing. Both files and directories have their last modified time listed and files also their size. The result is similar to an Apache server's directory listing.

Screen Shot

The icons used are thanks to FamFamFam.com.

Source Code

FileList.php

<?php
namespace com\dunweber\utils;
// ========================================================================
// FileList - Nicely list dirs and files
// Version: 2019-10-21 21:37:00 (UTC+02:00)
// https://www.dunweber.com/docs/scripts/releases/filelist
// Copyright (C) Christian L. Dünweber
// This program is licensed under the MIT License:
// https://opensource.org/licenses/MIT
// Icons thanks to: http://www.famfamfam.com/
// ========================================================================

class FileList
{
    
// Configuration:
    
public const

    
// Sorting direction for both dirs and files (though separately grouped)
    
SORT_ORDER SORT_ASC,

    
// Time format for dir and file modification time shown
    
TIME_FORMAT '%Y-%m-%d %H:%M:%S',

    
// Show hidden files or not (names that start with . are hidden)
    
SHOW_HIDDEN false,

    
// Web path to icons (with trailing slash)
    
ICONS_DIR 'icons/',

    
// All directories get this icon
    
DIR_ICON 'dir.png',

    
// Any file type not listed below gets this icon
    
GENERIC_ICON 'generic.png',

    
// File type icon association
    
FILE_TYPE_ICONS = [
    [
'acrobat.png',     ['pdf']],
    [
'application.png', ['exe','bat','cmd','com','msi','jar']],
    [
'code_red.png',    ['css']],
    [
'compress.png',    ['gz','zip','7z']],
    [
'compress_rar.png',['rar']],
    [
'excel.png',       ['xls','xlsx','csv']],
    [
'film.png',        ['avi','mpg','mpeg','wmv','mov','3gp','mp4']],
    [
'page_world.png',  ['html','htm','shtml','xhtml','dhtml','asp']],
    [
'code_blue.png',   ['js','java','xml','c','h','inc','ps1']],
    [
'json.png',        ['json']],
    [
'odg.png',         ['odg']],
    [
'picture.png',     ['jpg','jpeg','png','gif','tif','tiff','ico','bmp']],
    [
'php.png',         ['php','phps']],
    [
'powerpoint.png',  ['ppt','pptx','pps','pot']],
    [
'sound.png',       ['mp3','wma','mid','wav']],
    [
'sketchup.png',    ['skp']],
    [
'text.png',        ['txt','rtf','nfo']],
    [
'word.png',        ['doc','docx','dot','dotx']]
    ];

    
// ====================================================================
    // Get complete table listing all read content.
    // --------------------------------------------------------------------
    
public function getDirContent(string $dir '.'): string
    
{
        return
            
'<table class="fileList">
            <tr><td class="icon"><img src="'
.Self::ICONS_DIR.'back.png" alt="" /></td>'.
            
'<td><a href="..">Up</a></td></tr>'.
            
$this->getFormattedContent($dir).
            
'</table>';
    }

    
// ====================================================================
    // Create formatted table rows for all dirs and files read.
    // --------------------------------------------------------------------
    
private function getFormattedContent(string $dir): string
    
{
        
$content $this->readDir($dir); 

        if (
$content === false) {
            return 
formatErrorMessage('Could not read directory <em>'.$dir.'</em>');
        }

        
$dirs $content['dirs'];
        
$files $content['files'];

        if (
count($dirs) == && count($files) == 0) {
            return 
formatErrorMessage('<em>No files or directories found.</em>');
        }

        
$dirList '';
        
$fileList '';

        foreach (
$dirs as $dir) {
            
$dirList .= $this->getRow($dir['ico'], $dir['name'], ''$dir['time']);
        }

        foreach (
$files as $file) {
            
$fileList .= $this->getRow($file['ico'], $file['name'],
                
$this->getFriendlySize($file['size']), $file['time']);
        }

        return 
$dirList $fileList;
    }

    
// ====================================================================
    // Format error message to fit in the table.
    // --------------------------------------------------------------------
    
private function formatErrorMessage(string $msg): string
    
{
        return 
'<tr><td>&nbsp;</td><td>'.$msg.'</td></tr>';
    }

    
// ====================================================================
    // Make table row.
    // --------------------------------------------------------------------
    
private function getRow(string $icostring $namestring $sizestring $time): string
    
{
        return
            
'<tr>'.
            
'<td class="icon"><img src="'.Self::ICONS_DIR.$ico.'" alt="" /></td>'.
            
'<td><a href="'.htmlspecialchars($name).'">'.htmlspecialchars($name).'</a></td>'.
            
'<td>'.$size.'</td>'.
            
'<td>'.strftime(Self::TIME_FORMAT$time).'</td>'.
            
'</tr>'"\n";
    }

    
// ====================================================================
    // Read dir content, sort and separate dirs and files.
    // --------------------------------------------------------------------
    
private function readDir(string $dir)
    {
        if ((
$content scandir($dirSCANDIR_SORT_NONE)) === false) {
            return 
false;
        }

        
// Skip this and parent dir
        
$content array_diff($content, array('.','..'));

        if (
Self::SHOW_HIDDEN !== true) {
            
$content preg_grep('/^([^.])/'$content);
        }

        
// Sort the content naturally and case-insensitive
        
natcasesort($content);
        
        if (
Self::SORT_ORDER === SORT_DESC) {
            
$content array_reverse($content);
        }

        
$dirs = [];
        
$files = [];

        
// Separate dirs and files
        
foreach ($content as $filename) {
            
$file realpath($dir).DIRECTORY_SEPARATOR.$filename;

            if (
is_dir($file)) {
                
$dirs[] = ['name' => $filename'time' => filemtime($file),
                    
'ico' => $this->fileTypeIcon($filenametrue)];
            }
            else {
                
$files[] = ['name' => $filename'time' => filemtime($file),
                    
'ico' => $this->fileTypeIcon($filenamefalse), 'size' => filesize($file)];
            }
        }

        return [
'dirs' => $dirs'files' => $files];
    }

    
// ====================================================================
    // Get icon according to file extension.
    // --------------------------------------------------------------------
    
private function fileTypeIcon(string $filebool $isdir): string
    
{
        if (
$isdir) {
            return 
Self::DIR_ICON;
        }

        
$ext mb_strtolower(pathinfo($filePATHINFO_EXTENSION));

        if (
strlen($ext) == 0) {
            return 
Self::GENERIC_ICON;
        }

        
$result '';
        
        for (
$i 0$i count(Self::FILE_TYPE_ICONS); $i++) {
            if (
in_array($extarray_map('mb_strtolower',
                    
Self::FILE_TYPE_ICONS[$i][1]))) {
                
$result Self::FILE_TYPE_ICONS[$i][0];
                break;
            }
        }
        
        return (
strlen($result) > 0) ? $result Self::GENERIC_ICON;
    }

    
// ====================================================================
    // Present a data size in bytes as a human-readable with SI prefix.
    // Parameter $bytesize will normally come from filesize().
    // --------------------------------------------------------------------
    
private function getFriendlySize(int $bytesizeint $precision 2): string
    
{
        
$sizes = array('YB''ZB''EB''PB''TB''GB''MB''kB''B');
        
$total count($sizes);
    
        while (
$total-- && $bytesize 1024) {$bytesize /= 1024;}
        return 
round($bytesize$precision).' '.$sizes[$total];
    }
}

?>