[PHP-users 401] ちょっと複雑な並べ替えについて (usort)

Osamu Shigematsu php-users@php.gr.jp
Fri, 29 Jun 2001 15:34:35 +0900


重松と申します。

勉強のためディレクトリの一覧を表示するスクリプトを作っているのですが、ソート
の方法がわかりません。
正確にいえば、ソートする方法は知っているのですが、それではいまいち美しくない
ので、もっとうまい方法がないかと思っています。

現在は、単なる連想配列にディレクトリの中のファイルのファイル名、更新日、サイ
ズを入れてあって、ただの function を usort に渡して並べ替えています。

普通は、file_class というクラスでも作って、それに対して operator< だかを定義
すれば、きれいに並んでとても幸せなのですが、php だとそういう解決は可能なので
しょうか?

クラスのメソッドとして定義した関数を呼ぶことができれば、グローバル変数を作っ
たり、並べ替え関数を複数作ったりするという、いまいちなコードを書かなくて済む
のですが、どのようにすれば、良いのでしょうか? 以下の場合、クラスのメソッドで
ある、comp_files を呼びたいのですが。

アドバイス、よろしくお願いいたします。

P.S.
以下のソースは、http://www.spencernetwork.org/ にあるものを参考、というか、
ほとんどそのまま利用させて頂いてます。
私が使うのに必要のない機能なんかを削って、「私が」利用しやすいようにクラス化
したものです。

<?php

function comp_name($lhs,$rhs){
    return strcmp($lhs[0],$rhs[0]) * $GLOBALS["reverse"];
}

function comp_lastmod($lhs,$rhs){
    if($x = $lhs[1]-$rhs[1]) return $x * $GLOBALS["reverse"];
    return comp_name($lhs,$rhs);
}

function comp_filesize($lhs,$rhs){
    if($x = $lhs[2]-$rhs[2]) return $x * $GLOBALS["reverse"];
    return comp_name($lhs,$rhs);
}

class finder{
    var $filter = "[.](bin|sit|hqx|tgz|gz)\$";
    var $path = "./";
    var $base_path = "";
    var $sort_column = "name";
    var $sort_order = "a";
    var $icon_path = "/icons/";
    var $unknown_icon ="unknown.gif";
    var $icon = array(
        "txt"  => "text.gif",
        "html" => "layout.gif",
        "shtml"=> "layout.gif",
        "htm"  => "layout.gif",
        "gif"  => "image2.gif",
        "jpg"  => "image2.gif",
        "bmp"  => "image2.gif",
        "png"  => "image2.gif",
        "cgi"  => "script.gif",
        "tar"  => "tar.gif",
        "hqx"  => "binhex.gif",
        "zip"  => "compressed.gif",
        "lzh"  => "compressed.gif",
        "gz"   => "compressed.gif",
        "tgz"  => "compressed.gif",
        "sit"  => "compressed.gif",
        "bin"  => "compressed.gif",
        "php"  => "script.gif",
        "phps" => "script.gif",
        "php3" => "script.gif",
        "inc"  => "script.gif",
        "ihtml"=> "script.gif",
        "c"    => "c.gif");
    var $data;
    var $valid = false;

    function get_extension($filename){
            return
strtolower(ereg_replace(".*[.]([^~.]+)~?$","\\1",$filename));
    }

    function comp_files($lhs,$rhs){
        $sing = ($this->sort_order=="a") ? 1 : -1;
        switch($this->sort_column){
            case "lastmod":
                if($x = $lhs[1]-$rhs[1]) return $x * $sign;
                break;
            case "filesize":
                if($x = $lhs[2]-$rhs[2]) return $x * $sign;
                break;
        }
        return strcmp($lhs[0],$rhs[0]);
    }

    function dispatch(){
        $this->data = array();
        $this->valid = false;

        if(!@chdir($this->path))
            return "Cannot change directory to \"" . $this->$path ."\".";

        if(!($dir = @opendir($this->path)))
            return "Cannot open the directory \"" . $this->path ."\".";

        for(;$file = readdir($dir);){
            if(@is_dir($this->path.$file) || !@eregi($this->filter,$file))
continue;
            if($info = @stat($this->path.$file)){
                $lastmod  = $info[9];
                $filesize = $info[7];
                $this->data[] = array($file,$lastmod,$filesize);
            }
        }

        @closedir($dir);

        switch($this->sort_column){
            case "name":
            case "lastmod":
            case "filesize":
                break;
            default:
                $this->sort_column = "name";
        }
        $func = "comp_" . $this->sort_column;
        $GLOBALS["reverse"] = ($this->sort_order=="a") ? 1 : -1;
        usort($this->data,$func);

        $this->valid = true;

        return false;
    }

    function import(){
        switch($x = $GLOBALS["sort_column"]){
            case "name":
            case "lastmod":
            case "filesize":
            $this->sort_column = $x;
        }

        switch($x = $GLOBALS["sort_order"]){
            case "a": $this->sort_order = "d"; break;
            case "d": $this->sort_order = "a"; break;
        }
    }

    function reset_data(){ reset($this->data); }
    function next_data(){
        global $icon_uri,$ext,$file,$file_uri,$lastmod,$filesize;
        if(list(,$info) = each($this->data)){
            $file     = $info[0];
            $file_uri = urlencode($this->base_path . $file);
            $ext      = $this->get_extension($file);
            $icon_uri = $this->icon_path . (($icon = $this->icon[$ext]) ?
$icon : $this->unknown_icon);
            $lastmod  = date("Y-m-d",$info[1]);
            $filesize = $info[2];
            if($filesize >= 1048576){ // 1024*1024
                $filesize = sprintf("%.1fM",$filesize/1048576);
            }elseif($filesize >= 1024){
                $filesize = sprintf("%.1fK",$filesize/1024);
            }
        }
        return $info;
    }
}

?>

--
Osamu Shigematsu