Skip to content

Instantly share code, notes, and snippets.

@fer
Created October 7, 2012 16:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fer/3848828 to your computer and use it in GitHub Desktop.
Save fer/3848828 to your computer and use it in GitHub Desktop.
PHP FileSystem using Composite Pattern
<?php
# ············································································
# Filename: ls.php
# Syntax: php ls.php -d=directory -s
# Options:
# -d=directory (required) input directory to show (default=current)
# -s displays size in bytes (default=disabled)
# Description: Builds a hierarchical representation of the filesystem using
# a composite design pattern http://en.wikipedia.org/wiki/Composite_pattern
# ············································································
# Examples:
#
# fer@local:~/Documents$ php ls.php
# Projects
# Source
# Repos
# README.md
#
# fer@local:~/Documents$ php ls.php -s
# 22911 bytes Projects
# 4110 bytes Source
# 3288 bytes Repos
# 1091 bytes README.md
#
# fer@local:~/Documents$ php ls.php -s -d=../Desktop/Muse\ 2nd\ Law/
# 208 bytes Tracklist.txt
# 200 bytes Muse 2nd Law 2012 320kbps Mp3.zip.xml
# 104092497 bytes Muse 2nd Law 2012 320kbps Mp3.zip
# 43613 bytes Muse 2nd Law Cover.jpeg
# 49 bytes ReadMe.txt
#
# fer@local:~$ php -v
# PHP 5.3.10-1ubuntu3.4 with Suhosin-Patch (cli) (built: Sep 12 2012 19:00:43)
###
### Composite Class Definitions (component, leaf & composite classes)
###
# Component class: FileSystem
# Description: declares interfaces for constructor and output methods
class FileSystem {
protected $_name, $_size;
function __construct($name=null, $size=null){
$this->_size = $size;
$this->_name = $name;
}
function __toString(){
if ($this->_size)
return str_pad($this->_size, 30) . $this->_name."\n";
else
return $this->_name . "\n";
}
}
# Leaf class: File
class File extends FileSystem { }
# Composite class: Folder
class Folder extends FileSystem {
protected $_children = array();
function addChild(FileSystem $element){
$this->_children[] = $element;
}
function __toString(){
if ($this->_size)
$str = str_pad($this->_size, 30) . $this->_name."\n";
elseif ($this->_name)
$str = $this->_name . "\n";
else
$str = "";
foreach ($this->_children as $child)
$str .= (string) $child;
return $str;
}
}
###
### Helper functions (filesize_r & init_structure)
###
# Returns filesize in bytes
function filesize_r($path){
if (!file_exists($path)) return 0;
if (is_file($path)) return filesize($path) . " bytes";
$ret = 0;
foreach(glob($path."/*") as $fn) $ret += filesize_r($fn);
return $ret . " bytes";
}
# Maps files and dirs in the "composite pattern" structure
function init_structure($directory, $show_size=false){
# Create main container
$initial_folder = new Folder();
# Read system folder
if ($handle = opendir($directory)) {
while (false !== ($entry = readdir($handle))) {
# Skip parent directories
if ($entry != "." && $entry != "..") {
# Build path & show size check
$route = $directory."/".$entry;
($show_size) ? $size = filesize_r($route) : $size = null;
# Directory check & instantiation
if (is_dir($route."/"))
$initial_folder->addChild(new Folder($entry, $size));
# File check & instantiation
if (is_file($route))
$initial_folder->addChild(new File($entry, $size));
}
}
closedir($handle);
return $initial_folder;
}
}
###
### Main Flow (check params, execute init_structure)
###
$options = getopt("d::s");
(isset($options["d"])) ? $dir = $options["d"] : $dir = ".";
echo init_structure($dir, isset($options["s"]));
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment