File List [PHP]
Download Source Code
FileList.20191021-213700.zip [Downloads: 754]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) == 0 && 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> </td><td>'.$msg.'</td></tr>';
}
// ====================================================================
// Make table row.
// --------------------------------------------------------------------
private function getRow(string $ico, string $name, string $size, string $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($dir, SCANDIR_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($filename, true)];
}
else {
$files[] = ['name' => $filename, 'time' => filemtime($file),
'ico' => $this->fileTypeIcon($filename, false), 'size' => filesize($file)];
}
}
return ['dirs' => $dirs, 'files' => $files];
}
// ====================================================================
// Get icon according to file extension.
// --------------------------------------------------------------------
private function fileTypeIcon(string $file, bool $isdir): string
{
if ($isdir) {
return Self::DIR_ICON;
}
$ext = mb_strtolower(pathinfo($file, PATHINFO_EXTENSION));
if (strlen($ext) == 0) {
return Self::GENERIC_ICON;
}
$result = '';
for ($i = 0; $i < count(Self::FILE_TYPE_ICONS); $i++) {
if (in_array($ext, array_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 $bytesize, int $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];
}
}
?>