Created
August 10, 2011 03:04
-
-
Save k-holy/1135990 to your computer and use it in GitHub Desktop.
ディレクトリ内のファイル一覧(PHP5.2)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
error_reporting(E_ALL|E_STRICT); | |
if (defined('E_DEPRECATED')) { | |
error_reporting(error_reporting() & ~E_DEPRECATED); | |
} | |
mb_detect_order('ASCII,EUC-JP,SJIS,JIS,UTF-8'); | |
class U | |
{ | |
public static function NL($data) { | |
return str_replace("\r", "\n", str_replace("\r\n", "\n", $data)); | |
} | |
public static function H($data, $callback=null) { | |
if (isset($data) && strcmp($data, '') != 0) { | |
if (isset($callback)) { | |
$data = call_user_func($callback, $data); | |
} | |
$data = htmlspecialchars(self::NL($data), ENT_QUOTES, 'UTF-8'); | |
} | |
return $data; | |
} | |
} | |
class Holy_FileIterator implements Iterator, Countable | |
{ | |
protected $isDocumentRoot = false; | |
protected $index = 0; | |
protected $count = 0; | |
protected $files = array(); | |
public $directory; | |
public $sortKey; | |
public $ignorePrefixes; | |
public function __construct($dir, $types = null, $recursive = false, $ignorePrefixes = '.svn') | |
{ | |
$documentRoot = $_SERVER['DOCUMENT_ROOT']; | |
if (DIRECTORY_SEPARATOR === '\\') { | |
$dir = str_replace('\\', '/', $dir); | |
$documentRoot = str_replace('\\', '/', $documentRoot); | |
} | |
if (is_string($types)) { | |
$types = explode(',', $types); | |
} | |
$this->directory = $dir; | |
$this->isDocumentRoot = ($documentRoot === $dir); | |
$this->ignorePrefixes = $ignorePrefixes; | |
$this->files = $this->getFiles($dir, $types, $recursive); | |
$this->count = count($this->files); | |
} | |
public function getFiles($dir, $types = null, $recursive = false, $baseDir = '') | |
{ | |
$files = array(); | |
$dir = rtrim($dir, DIRECTORY_SEPARATOR); | |
if (DIRECTORY_SEPARATOR === '\\') { | |
$dir = str_replace('\\', '/', $dir); | |
} | |
if (DIRECTORY_SEPARATOR === '\\') { | |
$baseDir = str_replace('\\', '/', $baseDir); | |
} | |
if ($dir_handle = opendir($dir)) { | |
while (false !== ($filename = readdir($dir_handle))) { | |
if ($filename === '.' || $filename === '..') { | |
continue; | |
} | |
if (isset($this->ignorePrefixes)) { | |
$prefixes = explode(',', $this->ignorePrefixes); | |
$ignore = false; | |
foreach ($prefixes as $prefix) { | |
if (strpos($filename, $prefix) === 0) { | |
$ignore = true; | |
break; | |
} | |
} | |
if ($ignore) { | |
continue; | |
} | |
} | |
$path = $dir . DIRECTORY_SEPARATOR . $filename; | |
if (is_file($path) && is_array($types) && | |
!in_array(pathinfo($path, PATHINFO_EXTENSION), $types, true) | |
) { | |
continue; | |
} | |
$isDir = is_dir($path); | |
$file = array(); | |
$file['path' ] = $path; | |
$file['name' ] = $baseDir . $filename; | |
$file['size' ] = filesize($path); | |
$file['mtime' ] = filemtime($path); | |
$file['isDir' ] = $isDir; | |
$file['encoding'] = (file_exists($path) && is_file($path) && is_readable($path)) | |
? mb_detect_encoding(file_get_contents($path)) | |
: null; | |
$files[] = $file; | |
if ($recursive && $isDir) { | |
$subFiles = $this->getFiles($path, $types, $recursive, | |
$baseDir . $filename . DIRECTORY_SEPARATOR); | |
if (!empty($subFiles)) { | |
$files = array_merge($files, $subFiles); | |
} | |
} | |
} | |
closedir($dir_handle); | |
} | |
return $files; | |
} | |
public function sort($key, $desc=false) | |
{ | |
if (empty($this->files)) { | |
return; | |
} | |
if (!array_key_exists($key, $this->files[0])) { | |
throw new RuntimeException( | |
sprintf('Undefined sort key "%s" is specified.', $key)); | |
} | |
usort($this->files, function ($row1, $row2) use ($key, $desc) { | |
return ($desc) | |
? strnatcasecmp($row2[$key], $row1[$key]) | |
: strnatcasecmp($row1[$key], $row2[$key]); | |
}); | |
} | |
public function source($filename) | |
{ | |
if (strpos($filename, '..') !== false) { | |
throw new RuntimeException('invalid access.'); | |
} | |
$path = $this->directory . DIRECTORY_SEPARATOR . $filename; | |
if (file_exists($path) && is_file($path) && is_readable($path)) { | |
return file_get_contents($path); | |
} | |
return null; | |
} | |
public function isDocumentRoot() | |
{ | |
return $this->isDocumentRoot; | |
} | |
public function current() | |
{ | |
return $this->files[$this->index]; | |
} | |
public function key() | |
{ | |
return $this->index; | |
} | |
public function next() | |
{ | |
$this->index++; | |
} | |
public function rewind() | |
{ | |
$this->index = 0; | |
} | |
public function valid() | |
{ | |
return ($this->index < $this->count); | |
} | |
public function count() | |
{ | |
return $this->count; | |
} | |
} | |
$fileIterator = new Holy_FileIterator(dirname(__FILE__), 'html,php', true, '.svn'); | |
$sort = 'name'; | |
$desc = (isset($_GET['desc'])) ? (bool)$_GET['desc'] : false; | |
if (isset($_GET['sort']) && strlen($_GET['sort']) >= 1) { | |
$sort = $_GET['sort']; | |
} | |
$fileIterator->sort($sort, $desc); | |
if (isset($_GET['source'])) { | |
$source = $fileIterator->source($_GET['source']); | |
$source_path = $_GET['source']; | |
} | |
$encoding = (isset($source)) ? mb_detect_encoding($source) | |
: mb_detect_encoding(file_get_contents(__FILE__)); | |
$title = sprintf('%s @%s(%s)', dirname(__FILE__), $_SERVER['SERVER_NAME'], $_SERVER['SERVER_ADDR']); | |
?> | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="<?=U::H($encoding)?>" /> | |
<title><?=U::H($title)?></title> | |
<style type="text/css"> | |
body {font-family:monospace;} | |
table {border-collapse:collapse;border-spacing:0px;} | |
th,td {padding:4px; border:solid 1px #999999;} | |
div.source {border:dotted 1px #999999;padding:5px;} | |
</style> | |
</head> | |
<body> | |
<h1><?=U::H($title)?></h1> | |
<?php if (isset($source)) : ?> | |
<h2><?=U::H($source_path)?></h2> | |
<div class="source"><?=highlight_string($source, true)?></div> | |
<?php endif ?> | |
<table border="0" cellspacing="0"> | |
<caption>Total <?=U::H(count($fileIterator))?> Files</caption> | |
<thead> | |
<tr> | |
<th><a href="?sort=name">[asc]</a>NAME<a href="?sort=name&desc=1">[desc]</a></th> | |
<th><a href="?sort=mtime">[asc]</a>MTIME<a href="?sort=mtime&desc=1">[desc]</a></th> | |
<th><a href="?sort=size">[asc]</a>SIZE<a href="?sort=size&desc=1">[desc]</a></th> | |
<th><a href="?sort=encoding">[asc]</a>ENC<a href="?sort=encoding&desc=1">[desc]</a></th> | |
<th>ACTION</th> | |
</tr> | |
</thead> | |
<tbody> | |
<?php foreach ($fileIterator as $file) : ?> | |
<tr> | |
<td><a href="./<?=U::H($file['name' ])?>"><?=U::H($file['name'])?><?=U::H(($file['isDir']) ? '/' : '')?></a></td> | |
<td align="center"><?=U::H($file['mtime'], function ($var) { return date('Y-m-d H:i:s', $var); })?></td> | |
<td align="right"><?=U::H($file['size'], function ($var) { return number_format(sprintf('%u', $var)); })?></td> | |
<td><?=U::H($file['encoding'])?></td> | |
<td><a href="?source=<?=U::H($file['name'])?>">source</a></td> | |
<?php endforeach ?> | |
</tbody> | |
</table> | |
<?php if (false === $fileIterator->isDocumentRoot()) :?> | |
<p><a href="../">../(parent directory)</a></p> | |
<?php endif ?> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
イテレータで実装、usort()によるソート処理でクロージャを使ってみた。
(実は、クロージャを使わないといけない状況に遭遇したのは初めてだったりする)
最初はPHP5らしく、SPLのRecursiveDirectoryIteratorで実装しようとしたけど、ソートがめんどくさそうだったので断念。
source()とかこのクラスに付いてるのはおかしいけど気にしない…。