Skip to content

Instantly share code, notes, and snippets.

@k-holy
Created August 10, 2011 03:04
Show Gist options
  • Save k-holy/1135990 to your computer and use it in GitHub Desktop.
Save k-holy/1135990 to your computer and use it in GitHub Desktop.
ディレクトリ内のファイル一覧(PHP5.2)
<?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>
@k-holy
Copy link
Author

k-holy commented Aug 10, 2011

イテレータで実装、usort()によるソート処理でクロージャを使ってみた。
(実は、クロージャを使わないといけない状況に遭遇したのは初めてだったりする)
最初はPHP5らしく、SPLのRecursiveDirectoryIteratorで実装しようとしたけど、ソートがめんどくさそうだったので断念。
source()とかこのクラスに付いてるのはおかしいけど気にしない…。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment