From 0af252ad556a30377857f3965f027c1bdf20b434 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Mon, 3 Mar 2008 07:53:43 +0000 Subject: [PATCH] ordering and limited resultsets --- filemanager/cli.php | 6 +- filemanager/inc/class.filemanager_ui.inc.php | 35 +++------- filemanager/templates/default/index.xet | 5 +- phpgwapi/inc/class.egw_vfs.inc.php | 69 +++++++++++++++++++- 4 files changed, 83 insertions(+), 32 deletions(-) diff --git a/filemanager/cli.php b/filemanager/cli.php index fcf749ae64..a32beb083c 100755 --- a/filemanager/cli.php +++ b/filemanager/cli.php @@ -4,7 +4,7 @@ * Filemanager - Command line interface: ls * * @link http://www.egroupware.org - * @package admin + * @package filemanager * @author Ralf Becker * @copyright (c) 2006 by Ralf Becker * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License @@ -58,7 +58,7 @@ function usage($action=null,$ret=0) echo "\t$cmd chmod [-r|--recursive] mode=[ugoa]*[+-=][rwx]+,... URL [URL2 ...]\n"; echo "\t$cmd chown [-r|--recursive] user URL [URL2 ...]\n"; echo "\t$cmd chgrp [-r|--recursive] group URL [URL2 ...]\n"; - echo "\t$cmd find URL [URL2 ...] [-type (d|f)][-depth][-mindepth n][-maxdepth n][-mime type[/sub]][-name pattern][-path pattern][-uid id][-user name][-nouser][-gid id][-group name][-nogroup][-size N][-cmin N][-ctime N][-mmin N][-mtime N] (N: +n --> >n, -n --> =n)\n"; + echo "\t$cmd find URL [URL2 ...] [-type (d|f)][-depth][-mindepth n][-maxdepth n][-mime type[/sub]][-name pattern][-path pattern][-uid id][-user name][-nouser][-gid id][-group name][-nogroup][-size N][-cmin N][-ctime N][-mmin N][-mtime N] (N: +n --> >n, -n --> =n) [-limit N[,n]][-order (name|size|...)][-sort (ASC|DESC)]\n"; echo "\t$cmd mount URL [path] (without path prints out the mounts)\n"; echo "\t$cmd umount URL|path\n"; @@ -94,7 +94,7 @@ while(!is_null($option = array_shift($argv))) { if (!in_array($option,array('-type','-depth','-mindepth','-maxdepth','-name','-path', '-uid','-user','-nouser','-gid','-group','-nogroup','-mime', - '-empty','-size','-cmin','-ctime','-mmin','-mtime'))) + '-empty','-size','-cmin','-ctime','-mmin','-mtime','-limit','-order','-sort'))) { usage(); } diff --git a/filemanager/inc/class.filemanager_ui.inc.php b/filemanager/inc/class.filemanager_ui.inc.php index 69caff795b..7580cc840c 100644 --- a/filemanager/inc/class.filemanager_ui.inc.php +++ b/filemanager/inc/class.filemanager_ui.inc.php @@ -3,7 +3,7 @@ * Filemanager - user interface * * @link http://www.egroupware.org - * @package admin + * @package filemanager * @author Ralf Becker * @copyright (c) 2008 by Ralf Becker * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License @@ -42,33 +42,15 @@ class filemanager_ui { $content['nm'] = array( 'get_rows' => 'filemanager.filemanager_ui.get_rows', // I method/callback to request the data for the rows eg. 'notes.bo.get_rows' -// 'filter_label' => // I label for filter (optional) -// 'filter_help' => // I help-msg for filter (optional) 'no_filter' => True, // I disable the 1. filter 'no_filter2' => True, // I disable the 2. filter (params are the same as for filter) 'no_cat' => True, // I disable the cat-selectbox -// 'cat_app' => // I application the cat's should be from, default app in get_rows -// 'template' => // I template to use for the rows, if not set via options -// 'header_left' => // I template to show left of the range-value, left-aligned (optional) -// 'header_right' => // I template to show right of the range-value, right-aligned (optional) -// 'bottom_too' => True// I show the nextmatch-line (arrows, filters, search, ...) again after the rows -// 'never_hide' => True, // I never hide the nextmatch-line if less then maxmatch entrie // 'lettersearch' => True, // I show a lettersearch 'searchletter' => false, // I0 active letter of the lettersearch or false for [all] 'start' => 0, // IO position in list -// 'num_rows' => // IO number of rows to show, defaults to maxmatches from the general prefs -// 'cat_id' => // IO category, if not 'no_cat' => True -// 'search' => // IO search pattern 'order' => 'name', // IO name of the column to sort after (optional for the sortheaders) 'sort' => 'ASC', // IO direction of the sort: 'ASC' or 'DESC' -// 'col_filter' => // IO array of column-name value pairs (optional for the filterheaders) -// 'filter' => // IO filter, if not 'no_filter' => True -// 'filter_no_lang' => True// I set no_lang for filter (=dont translate the options) -// 'filter_onchange'=> 'this.form.submit();'// I onChange action for filter, default: this.form.submit(); -// 'filter2' => // IO filter2, if not 'no_filter2' => True -// 'filter2_no_lang'=> True// I set no_lang for filter2 (=dont translate the options) -// 'filter2_onchange'=> 'this.form.submit();'// I onChange action for filter, default: this.form.submit(); - 'default_cols' => '!comment', // I columns to use if there's no user or default pref (! as first char uses all but the named columns), default all columns + 'default_cols' => '!comment,ctime', // I columns to use if there's no user or default pref (! as first char uses all but the named columns), default all columns 'csv_fields' => false, // I false=disable csv export, true or unset=enable it with auto-detected fieldnames, //or array with name=>label or name=>array('label'=>label,'type'=>type) pairs (type is a eT widget-type) 'path' => '/home/'.$GLOBALS['egw_info']['user']['account_lid'], @@ -336,12 +318,13 @@ class filemanager_ui $dir_is_writable = egw_vfs::is_writable($query['path']); $rows = array(); - foreach(egw_vfs::find($query['path'],array('mindepth'=>1,'maxdepth'=>1)) as $path) + foreach(egw_vfs::find($query['path'],array( + 'mindepth' => 1, 'maxdepth' => 1, // no recursion into subdirs + 'order' => $query['order'], 'sort' => $query['sort'], + 'limit' => (int)$query['num_rows'].','.(int)$query['start'], + 'need_mime' => true, + ),true) as $path => $row) { - $row = egw_vfs::stat($path); - $row['name'] = egw_vfs::basename($path); - $row['path'] = $path; - $row['mime'] = egw_vfs::mime_content_type($path); $row['icon'] = self::mime_icon($row['mime']); $row['perms'] = egw_vfs::int2mode($row['mode']); // only show link if we have access to the file or dir @@ -371,6 +354,6 @@ class filemanager_ui } } //_debug_array($readonlys); - return count($rows); + return egw_vfs::$find_total; } } \ No newline at end of file diff --git a/filemanager/templates/default/index.xet b/filemanager/templates/default/index.xet index 224d42037f..1b8e62a908 100644 --- a/filemanager/templates/default/index.xet +++ b/filemanager/templates/default/index.xet @@ -8,6 +8,7 @@ + @@ -16,10 +17,11 @@ - + + @@ -34,6 +36,7 @@ + diff --git a/phpgwapi/inc/class.egw_vfs.inc.php b/phpgwapi/inc/class.egw_vfs.inc.php index f326507144..6ca65dd62b 100644 --- a/phpgwapi/inc/class.egw_vfs.inc.php +++ b/phpgwapi/inc/class.egw_vfs.inc.php @@ -84,6 +84,12 @@ class egw_vfs extends vfs_stream_wrapper * @var int */ static $user; + /** + * Total of last find call + * + * @var int + */ + static $find_total; /** * fopen working on just the eGW VFS @@ -251,6 +257,10 @@ class egw_vfs extends vfs_stream_wrapper * - ctime/mtime => (+|-|)N file/dir created/modified in the last N days * - depth => (+|-)N * - url => false(default),true allow (and return) full URL's instead of VFS pathes (only set it, if you know what you doing securitywise!) + * - need_mime => false(default),true should we return the mime type + * - order => name order rows by name column + * - sort => (ASC|DESC) sort, default ASC + * - limit => N,[n=0] return N entries from position n on, which defaults to 0 * @param string/array/true $exec=null function to call with each found file or dir as first param or * true to return file => stat pairs * @param array $exec_params=null further params for exec as array, path is always the first param! @@ -294,6 +304,10 @@ class egw_vfs extends vfs_stream_wrapper $options['gid'] = 0; } } + if ($options['order'] == 'mime') + { + $options['need_mime'] = true; // we need to return the mime colum + } $url = $options['url']; if (!is_array($base)) @@ -338,6 +352,8 @@ class egw_vfs extends vfs_stream_wrapper $opts = $options; if ($opts['mindepth']) $opts['mindepth']--; if ($opts['maxdepth']) $opts['maxdepth']++; + unset($opts['order']); + unset($opts['limit']); foreach(self::find($options['url']?$file:parse_url($file,PHP_URL_PATH),$opts,true) as $p => $s) { unset($result[$p]); @@ -352,6 +368,47 @@ class egw_vfs extends vfs_stream_wrapper self::_check_add($options,$path,$result); } } + // ordering of the rows + if (isset($options['order'])) + { + $sort = strtolower($options['sort']) == 'desc' ? '-' : ''; + switch($options['order']) + { + // sort numerical + case 'size': + case 'uid': + case 'gid': + case 'mode': + case 'ctime': + case 'mtime': + uasort($result,create_function('$a,$b',$c='return '.$sort.'($a[\''.$options['order'].'\']-$b[\''.$options['order'].'\']);')); + break; + + // sort alphanumerical + default: + $options['order'] = 'name'; + // fall throught + case 'name': + case 'mime': + case 'comment': // ToDo: fetch it for sqlfs or oldvfs + uasort($result,create_function('$a,$b',$c='return '.$sort.'strcasecmp($a[\''.$options['order'].'\'],$b[\''.$options['order'].'\']);')); + break; + } + //echo "order='$options[order]', sort='$options[sort]' --> '$c'
\n"; + } + // limit resultset + self::$find_total = count($result); + if (isset($options['limit'])) + { + list($limit,$start) = explode(',',$options['limit']); + if (!$limit && !($limit = $GLOBALS['egw_info']['user']['preferences']['comman']['maxmatches'])) $limit = 15; + //echo "total=".egw_vfs::$find_total.", limit=$options[limit] --> start=$start, limit=$limit
\n"; + + if ((int)$start || self::$find_total > $limit) + { + $result = array_slice($result,(int)$start,(int)$limit,true); + } + } //echo $path; _debug_array($result); if ($exec !== true && is_callable($exec)) { @@ -394,8 +451,16 @@ class egw_vfs extends vfs_stream_wrapper if (!($stat = self::url_stat($path,0))) { return; // not found, should not happen + } + $stat = array_slice($stat,13); // remove numerical indices 0-12 + $stat['name'] = self::basename($path); + $stat['path'] = $path; + if ($options['mime'] || $options['need_mime']) + { + $stat['mime'] = self::mime_content_type($path); } - if (isset($options['name_preg']) && !preg_match($options['name_preg'],self::basename($path)) || + + if (isset($options['name_preg']) && !preg_match($options['name_preg'],$stat['name']) || isset($options['path_preg']) && !preg_match($options['path_preg'],$path)) { return; // wrong name or path @@ -405,7 +470,7 @@ class egw_vfs extends vfs_stream_wrapper { return; // wrong user or group } - if (isset($options['mime']) && $options['mime'] != ($mime = self::mime_content_type($path))) + if (isset($options['mime']) && $options['mime'] != $stat['mime']) { list($type,$subtype) = explode('/',$options['mime']); // no subtype (eg. 'image') --> check only the main type