ファイルリストの一覧をソートする

ファイルリストの一覧をソートする

- Tatsuya Shirai の投稿
返信数: 5

 ディスカッショントピックのソーティングが成功したことに気を良くして,ファイルリストの一覧もソーティングしてみました.ウインク

 いまの所は,[サイト管理]-[ファイル](あるいは”ファイルを編集する”)の一覧のみ改良を行っただけですが,なかなか使い易そうです.ファイル数が膨大になってくると役に立ちます.

 続いて,リソースの追加の”フォルダの表示”も対応させる予定です.しかしまぁ,よく似た機能だというのにソースが別々というのは効率が悪い.欲を言えばHTMLエディタ(htmlarea)のファイル編集画面も対応させたいところですが,こちらは重要性があまり高くないので対応しない予定です.

 もう暫く様子を見てから修正箇所を報告します.

対応したソート:ファイル名,ファイルサイズ,更新日時による昇順/降順のソート.

PS1. なお,オリジナルはファイル名によるソート(一方向)のみです.
PS2. サンプル画面ではフォルダのサイズでソートしています.当然ながらフォルダとファイルが混在した状態でもソーティングできます.

添付 sortfilelist.jpg
Tatsuya Shirai への返信

Re: ファイルリストの一覧をソートする

- Tatsuya Shirai の投稿
 ディスカッショントピックの一覧表示のソーティングも,このように(’評定’のパクリ?)見出しの横に記号(ボタン)を配置したかったのですが,最初に投稿した日時の欄が存在しないので諦めました.かといって,”最初に投稿”した日付の列を追加すると画面が狭くなりますからね.
Tatsuya Shirai への返信

Re: ファイルリストの一覧をソートする

- Tatsuya Shirai の投稿

 リソースの”ディレクトリの表示”におけるファイル/フォルダのソーティングも何とか完成しました.やはりバグが色々と明らかになってきましたので,あと1日くらいは寝かしてから報告します.

 ”ディレクトリの表示”では”一つ上のフォルダ”のアイコンが表示されません.ブラウザの”戻る”あるいはNaviバーを使用すれば一つ上のフォルダに戻ることは可能である,と結論付けました.万が一,コードのミスで公開していないフォルダ内まで見えてしまうとセキュリティ上の問題がある,という判断で意図的に付けていない機能なのでしょう.

Tatsuya Shirai への返信

Re: ファイルリストの一覧をソートする

- Tatsuya Shirai の投稿

 パッチを投稿します.多分,大丈夫でしょう.

 ソーティングを行うために,意外とソースリストに手を入れる必要が生じました.
 この修正は大きく分けて,

  1. [サイト管理]-[ファイル]および"ファイル編集"のフォルダ内一覧表示
  2. リソースの追加/ディレクトリの表示のフォルダ内一覧表示

に分けられます.フォルダ内一覧表示が独立しているのですから致し方ありません...

 以下に,2つに分けて投稿します.

Tatsuya Shirai への返信

Re: ファイルリストの一覧をソートする

- Tatsuya Shirai の投稿

[サイト管理]-[ファイル]および"ファイル編集"のフォルダ内一覧表示

(1) files/index.php: 25行近辺,パラメータを取得する箇所.

    $id      = required_param('id', PARAM_INT);
    $file    = optional_param('file', '', PARAM_PATH);
    $wdir    = optional_param('wdir', '', PARAM_PATH);
    $action  = optional_param('action', '', PARAM_ACTION);
    $name    = optional_param('name', '', PARAM_FILE);
    $oldname = optional_param('oldname', '', PARAM_FILE);
    $choose  = optional_param('choose', '', PARAM_FILE); //in fact it is always 'formname.inputname'
    $userfile= optional_param('userfile','',PARAM_FILE);
    $save    = optional_param('save', 0, PARAM_BOOL);
    $text    = optional_param('text', '', PARAM_RAW);
    $confirm = optional_param('confirm', 0, PARAM_BOOL);
// ここから追加
    $sortorderfilelist = optional_param('sortorderfilelist', 0, PARAM_INT);
    if ($sortorderfilelist < 1) {
        if (isset($_SESSION['sortorderfilelist'])) $sortorderfilelist = $_SESSION['sortorderfilelist'];
            else $sortorderfilelist = 1;
    } else $_SESSION['sortorderfilelist'] = $sortorderfilelist;
// ここまで追加

    if ($choose) {
        if (count(explode('.', $choose)) > 2) {
            error('Incorrect format for choose parameter');
        }
    }

(2)files/index.php: function displaydir(), 811行近辺

function displaydir ($wdir) {
//  $wdir == / or /a or /a/b/c/d  etc

    global $basedir;
    global $id;
    global $USER, $CFG;
    global $choose;
    global $sortorderfilelist;  // (追加)

    $fullpath = $basedir.$wdir;
    $dirlist = array();

    $directory = opendir($fullpath);             // Find all files
    while (false !== ($file = readdir($directory))) {
        if ($file == "." || $file == "..") {
            continue;
        }

        if (is_dir($fullpath."/".$file)) {
// 以下3行をコメントアウト
//
          $dirlist[] = $file;
//      } else {
//          $filelist[] = $file;
//  ここから追加
            switch ($sortorderfilelist) {
              case 3: case 4:
                $sortkeystr = strftime('%Y%m%d%H%M%S', fs_filemtime("$fullpath/$file"));
                break;
              case 5: case 6:
                $sortkeystr = strval(get_directory_size("$fullpath/$file"));
                break;
              case 1: case 2: default:
                $sortkeystr = $file;
                break;
   }
            $dirlist['0'.$file] = $sortkeystr; 
            // $dirlist["0"]が$dirlist[0]になってしまうため'0'を付けて$dirlist["00"]とする.
        } else {
            switch ($sortorderfilelist) {
              case 3: case 4:
                $sortkeystr = strftime('%Y%m%d%H%M%S', fs_filemtime("$fullpath/$file"));
                break;
              case 5: case 6:
                $sortkeystr = strval(fs_filesize("$fullpath/$file"));
                break;
              default:
                $sortkeystr = $file; break;
   }
            $filelist['0'.$file] = $sortkeystr;
            // $filelist["0"]が$filelist[0]になってしまうため'0'を付けて$filelist["00"]とする.
// ここまで追加
        }
    }
    closedir($directory);

    $strname = get_string("name");
    $strsize = get_string("size");

(途中省略)

    $strrename = get_string("rename");
    $stredit   = get_string("edit");
    $strunzip  = get_string("unzip");
    $strlist   = get_string("list");
    $strrestore= get_string("restore");
    $strchoose = get_string("choose");
    $strfolder = get_string("folder");
    $strfile   = get_string("file");
// ここから追加
    $reloadurl = "<a href=\"index.php?id=$id&amp;wdir=$wdir&amp;choose=$choose&amp;";
    $strname .= "&nbsp(";
    $strname .= $sortorderfilelist == 1 ? "&#x25B2;/" : $reloadurl."sortorderfilelist=1\">&#x25B2;</a>/";
    $strname .= $sortorderfilelist == 2 ? "&#x25BC;)" : $reloadurl."sortorderfilelist=2\">&#x25BC;</a>)";
    $strmodified .= "&nbsp(";
    $strmodified .= $sortorderfilelist == 3 ? "&#x25B2;/" : $reloadurl."sortorderfilelist=3\">&#x25B2;</a>/";
    $strmodified .= $sortorderfilelist == 4 ? "&#x25BC;)" : $reloadurl."sortorderfilelist=4\">&#x25BC;</a>)";
    $strsize .= "&nbsp(";
    $strsize .= $sortorderfilelist == 5 ? "&#x25B2;/" : $reloadurl."sortorderfilelist=5\">&#x25B2;</a>/";
    $strsize .= $sortorderfilelist == 6 ? "&#x25BC;)" : $reloadurl."sortorderfilelist=6\">&#x25BC;</a>)";
// ここまで追加


    echo "<form action=\"index.php\" method=\"post\" id=\"dirform\">";
    echo "<div>";
    echo '<input type="hidden" name="choose" value="'.$choose.'" />';
    // echo "<hr align=\"center\" noshade=\"noshade\" size=\"1\" />";
    echo "<hr/>";
    echo "<table border=\"0\" cellspacing=\"2\" cellpadding=\"2\" width=\"640\" class=\"files\">";
    echo "<tr>";
    echo "<th class=\"header\" scope=\"col\"></th>";
    echo "<th class=\"header name\" scope=\"col\">$strname</th>";
    echo "<th class=\"header size\" scope=\"col\">$strsize</th>";
    echo "<th class=\"header date\" scope=\"col\">$strmodified</th>";
    echo "<th class=\"header commands\" scope=\"col\">$straction</th>";
    echo "</tr>\n";

    if ($wdir != "/") {
        $dirlist[] = '..';
    }

    $count = 0;

    if (!empty($dirlist)) {
// 以下2行をコメントアウト
//
      asort($dirlist);
//      foreach ($dirlist as $dir) {
// ここから追加
        switch ($sortorderfilelist) {
          case 2:  case 4: case 6:  arsort($dirlist); break;
          case 3:  case 5: default: asort($dirlist);  break;
        }
        foreach ($dirlist as $key => $value) {
            if ($value == '..') {
                unset($dirlist[$key]);
                $dirlist = array('0..'=>'..') + $dirlist;
            }
        }
        foreach ($dirlist as $dir => $dummy) {
            $dir = substr($dir, 1);  // 頭のダミーの'0'を取り除く
// ここまで追加
            echo "<tr class=\"folder\">";

            if ($dir == '..') {
                $fileurl = rawurlencode(dirname($wdir));
                print_cell();
                // alt attribute intentionally empty to prevent repetition in screen reader
                print_cell('left', '<a href="index.php?id='.$id.'&amp;wdir='.$fileurl.'&amp;choose='.$choose.'"><img src="'.$CFG->pixpath.'/f/parent.gif" class="icon" alt="" />&nbsp;'.get_string('parentfolder').'</a>', 'name');
                print_cell();
                print_cell();
                print_cell();

            } else {
                $count++;
                $filename = $fullpath."/".$dir;
                $fileurl  = rawurlencode($wdir."/".$dir);
                $filesafe = rawurlencode($dir);
                $filesize = display_size(get_directory_size("$fullpath/$dir"));
                $filedate = userdate(filemtime($filename), "%d %b %Y, %I:%M %p");
//              $filedate = userdate(filemtime($filename), "");     // タイムスタンプを年月日で表示したい場合はこちらをどうぞ
                print_cell("center", "<input type=\"checkbox\" name=\"file$count\" value=\"$fileurl\" />", 'checkbox');
                print_cell("left", "<a href=\"index.php?id=$id&amp;wdir=$fileurl&amp;choose=$choose\"><img src=\"$CFG->pixpath/f/folder.gif\" class=\"icon\" alt=\"$strfolder\" />&nbsp;".htmlspecialchars($dir)."</a>", 'name');
                print_cell("right", $filesize, 'size');
                print_cell("right", $filedate, 'date');
// ここから追加 (これはソーティングではなく,リソース/ディレクトリの表示 でディレクトリをプルダウンリストではなくファイル編集画面から選択できるようにするための修正)
            if ($choose == 'id_reference2_value') {
                $selectdir = trim($fileurl, "/");
                $edittext = "<strong><a Xonclick=\"return set_value('".rawurldecode($selectdir)."')\" href=\"#\">$strchoose</a></strong>&nbsp;";
            } else $edittext = '';
// ここまで追加
//
              print_cell("right", "<a href=\"index.php?id=$id&amp;wdir=$wdir&amp;file=$filesafe&amp;action=rename&amp;choose=$choose\">$strrename</a>", 'commands');
                print_cell("right", "$edittext <a href=\"index.php?id=$id&amp;wdir=".rawurlencode($wdir)."&amp;file=$filesafe&amp;action=rename&amp;choose=$choose\">$strrename</a>", 'commands');  // $wdirをrawurlencode()しているのは本件と別件.IE対策です.$edittextを追加しているのは上述の通り.
            }

            echo "</tr>";
        }
    }


    if (!empty($filelist)) {
// 以下2行をコメントアウト
//
      asort($filelist);
//      foreach ($filelist as $file) {
// ここから追加
        switch ($sortorderfilelist) {
          case 2: case 4: case 6:  arsort($filelist); break;
          case 3: case 5: default: asort($filelist);  break;
        }
        foreach ($filelist as $file => $dummy) {
            $file = substr($file, 1);  // 頭のダミーの'0'を取り除く
// ここまで追加

            $icon = mimeinfo("icon", $file);


以上で良いはずです.

別件(リソースの追加/ディレクトリの表示のフォルダの選択をプルダウンリストだけではなく,ファイル編集画面を使って選択できるようにする拡張)なども混ざっているため見づらいですね.スミマセン.赤い文字のところが本件です.

Tatsuya Shirai への返信

Re: ファイルリストの一覧をソートする

- Tatsuya Shirai の投稿

リソースの追加/ディレクトリの表示のフォルダ内一覧表示

(1)mod/resource/type/directory/resource.class.php,ソースリストの一番トップ

<?php // $Id: resource.class.php,v 1.34.2.2 2007/11/08 05:36:21 toyomoyo Exp $

// ここから追加
    $sortorderfilelist = optional_param('sortorderfilelist', 0, PARAM_INT);
    if ($sortorderfilelist < 1) {
        if (isset($_SESSION['sortorderfilelist'])) $sortorderfilelist = $_SESSION['sortorderfilelist'];
            else $sortorderfilelist = 1;
    } else $_SESSION['sortorderfilelist'] = $sortorderfilelist;
// ここまで追加

class resource_directory extends resource_base {

(2)同上,function display(): 40行近辺

function display() {
    global $CFG;
    global $sortorderfilelist;  // ( (追加)

/// Set up generic stuff first, including checking for access
    parent::display();

/// Set up some shorthand variables
    $cm = $this->cm;
    $course = $this->course;
    $resource = $this->resource;

(3)同上,113行近辺

    if (trim(strip_tags($resource->summary))) {
        print_simple_box(format_text($resource->summary, FORMAT_MOODLE, $formatoptions, $course->id), "center");
        print_spacer(10,10);
    }

//  $files = get_directory_list("$CFG->dataroot/$relativepath", array($CFG->moddata, 'backupdata'), false, true, true);
// ここから追加
    $dirs = get_directory_list("$CFG->dataroot/$relativepath", array($CFG->moddata, 'backupdata'), false, true, false);
    $files = get_directory_list("$CFG->dataroot/$relativepath", array($CFG->moddata, 'backupdata'), false, false, true);
    $dirlist = $filelist = array();
    foreach ($dirs as $file) {
        switch ($sortorderfilelist) {
          case 3: case 4:
            $sortkeystr = strftime('%Y%m%d%H%M%S', fs_filemtime("$CFG->dataroot/$relativepath/$file"));
            break;
          case 5: case 6:
            $sortkeystr = strval(get_directory_size("$CFG->dataroot/$relativepath/$file"));
            break;
          case 1: case 2: default:
            $sortkeystr = $file;
            break;
  }
        $dirlist['0'.$file] = $sortkeystr; 
        // $dirlist["0"]が$dirlist[0]になってしまうため'0'を付けて$dirlist["00"]とする.
    }
    foreach ($files as $file) {
        switch ($sortorderfilelist) {
          case 3: case 4:
            $sortkeystr = strftime('%Y%m%d%H%M%S', fs_filemtime("$CFG->dataroot/$relativepath/$file"));
            break;
          case 5: case 6:
            $sortkeystr = strval(fs_filesize("$CFG->dataroot/$relativepath/$file"));
            break;
          default:
            $sortkeystr = $file; break;
  }
        $filelist['0'.$file] = $sortkeystr;
        // $filelist["0"]が$filelist[0]になってしまうため'0'を付けて$filelist["00"]とする.
    }
// ここまで追加


//  if (!$files) {  
    if (empty($dirlist) && empty($filelist)) {
        print_heading(get_string("nofilesyet"));
        print_footer($course);
        exit;
    }
    print_simple_box_start("center", "", "", '0' );

    $strftime = get_string('strftimedatetime');
    $strname = get_string("name");
    $strsize = get_string("size");
    $strmodified = get_string("modified");
    $strfolder = get_string("folder");
    $strfile = get_string("file");
// ここから追加
    $reloadurl = "<a href=\"view.php?id={$cm->id}&amp;subdir=".rawurlencode($subdir)."&amp;";
    $strname .= "&nbsp(";
    $strname .= $sortorderfilelist == 1 ? "&#x25B2;/" : $reloadurl."sortorderfilelist=1\">&#x25B2;</a>/";
    $strname .= $sortorderfilelist == 2 ? "&#x25BC;)" : $reloadurl."sortorderfilelist=2\">&#x25BC;</a>)";
    $strmodified .= "&nbsp(";
    $strmodified .= $sortorderfilelist == 3 ? "&#x25B2;/" : $reloadurl."sortorderfilelist=3\">&#x25B2;</a>/";
    $strmodified .= $sortorderfilelist == 4 ? "&#x25BC;)" : $reloadurl."sortorderfilelist=4\">&#x25BC;</a>)";
    $strsize .= "&nbsp(";
    $strsize .= $sortorderfilelist == 5 ? "&#x25B2;/" : $reloadurl."sortorderfilelist=5\">&#x25B2;</a>/";
    $strsize .= $sortorderfilelist == 6 ? "&#x25BC;)" : $reloadurl."sortorderfilelist=6\">&#x25BC;</a>)";
// ここまで追加

    echo '<table cellpadding="4" cellspacing="1" class="files" summary="">';
    echo "<tr><th class=\"header name\" scope=\"col\">$strname</th>".
         "<th align=\"right\" colspan=\"2\" class=\"header size\" scope=\"col\">$strsize</th>".
         "<th align=\"right\" class=\"header date\" scope=\"col\">$strmodified</th>".
         "</tr>";
//  foreach ($files as $file) {
// ここから追加
    switch ($sortorderfilelist) {
      case 2:  case 4: case 6:  arsort($dirlist); arsort($filelist); break;
      case 3:  case 5: default: asort($dirlist);  asort($filelist);  break;
    }
    $files = $dirlist + $filelist;  // 同名のフォルダとファイルは作成不可なので重複してもOK
    foreach ($files as $file => $dummy) {
        $file = substr($file, 1);  // 頭のダミーの'0'を取り除く
// ここまで追加
        if (is_dir("$CFG->dataroot/$relativepath/$file")) {          // Must be a directory
            $icon = "folder.gif";
            $relativeurl = "/view.php?blah";
            $filesize = display_size(get_directory_size("$CFG->dataroot/$relativepath/$file"));


以上で良いはずです.色々な修正を並行して行ったため,Subversionから正確な差分を得られませんでした.何かおかしなことがあったら報告して下さい.