Одним из самых простых способов публикации файлов является их размещение в пределах ветви файловой системы, доступной для просмотра в браузере. Как сделать такой «просмотрщик» на G-Drive, можно прочитать в данной статье.
Представленный в статье модуль не предназначен для отображения сразу всей структуры некоторой ветви файловой системы. В нем в ответ на каждый запрос отображаются оглавление отдельного каталога и строка навигации для перехода в один из вышележащих каталогов относительно текущего (отображаемого). Для получения оглавления каталога мной были использованы стандартные функции opendir, readdir и closedir. Основу модуля составляет следующий код:
$ps=strlen($p0)?'/':'';
$prefix='';
$base=$ps.$p0.'/';
$path=$ps.$px.'/';
$fullpath=$_SERVER['DOCUMENT_ROOT'].$ps.$px;
if (
realpath($fullpath)===strtr($fullpath,'/',DIRECTORY_SEPARATOR)&&
strncmp($path,$prefix.$base,strlen($prefix)+strlen($base))==0&&
chdir($fullpath)&&
($dir=opendir($fullpath))
)
{
$dirs=array();
$files=array();
while (($obj=readdir($dir))!==false)
{
if ($obj[0]!='.')
{
if (is_dir($obj)) $dirs[]=$obj;
else
{
$files[]=$obj;
$sizes[]=filesize($obj);
}
}
}
closedir($dir);
}
else error(404);
В коде реализовано наложение адресной ветви на ветвь файловой системы путем совмещения категории G-Drive с каталогом файловой системы, который является вершиной доступной для просмотра ветви файловой системы или находится выше нее.
Путь для адреса «вершины» (базовый путь) складывается из префикса и базы. База – это краткое имя вершины, обрамленное слешами, или слеш. Префикс – это часть пути до базы. Текущий путь определяется адресом текущего каталога и обязательно содержит завершающий слеш вне зависимости от его наличия в адресе. Полный путь – это полное имя текущего каталога в файловой системе. Он наоборот не содержит завершающий слеш (кроме случая, когда текущим является корневой каталог файловой системы).
Использование переменной $ps позволяет корректно задавать пути для пустой категории, что в свою очередь позволяет отображать оглавление каталога по адресу, состоящему из слеша, т.е. на главной странице сайта. Для отображения подкаталогов недостаточно подключения модуля только к пустой категории. Его также нужно подключить к категориям, которые соответствуют подкаталогам, нуждающимся в отображении. При этом к пустой категории можно подключить отдельный модуль, отображающий в качестве имен подкаталогов имена или символьные идентификаторы категорий, к которым подключен данный модуль.
В модуле также присутствует серверный код сортировки оглавления каталога. Добавьте к основному ветвлению в начало условия фрагмент $pn<4&& и в конец первого блока ветвления (сразу после команды закрытия каталога) фрагмент
if ($pn==1) rsort($dirs);
else sort($dirs);
if (count($files)) switch ($pn)
{
case 0:
array_multisort($files,$sizes);
break;
case 1:
array_multisort($files,SORT_DESC,$sizes);
break;
case 2:
array_multisort($sizes,$files);
break;
case 3:
array_multisort($sizes,SORT_DESC,$files);
}
function sortlink($s=0)
{
$p=$s<<1;
$p+=$GLOBALS['pn']==$p;
return $p?'?p='.$p:'';
}
Из кода видно, что сортировка может выполняться по имени и размеру файлов, по возрастанию и убыванию. Функция sortlink предназначена для добавления к адресу текущего каталога параметра, переключающего тип сортировки. Когда в параметре функции указан 0, адрес позволит выполнить сортировку по имени (установить тип сортировки 0 или 1), а когда 1 – по размеру файлов (установить тип сортировки 2 или 3). Ссылки с адресами для переключения целесообразно размещать в заголовках столбцов таблицы, содержащих соответственно имена и размеры файлов. Во всех прочих адресах каталогов нужно наследовать текущий тип сортировки. Для этого можно определить специальную переменную $term:
$term=$pn?'?p='.$pn:'';
Эту же переменную можно использовать для добавления к адресам каталогов завершающего слеша, немного изменив ее определение (только не добавляйте такой терминатор к адресу главной, а используйте его вместо адреса главной):
$term=$pn?'/?p='.$pn:'/';
Код вывода строки навигации для шаблона:
<p><?php $i=strlen($prefix); while (++$i<strlen($path)): ?>/<a href="<?= substr($path,0,$i=strpos($path,'/',$start=$i)),$term ?>"><?= substr($path,$start,$i-$start) ?></a><?php endwhile; ?></p>
И код вывода таблицы с оглавлением каталога:
<table cellspacing=0 id="fb"> <tr><th><a href="<?= $p,sortlink(0) ?>">Name</a></th><th class="num"><a href="<?= $p,sortlink(1) ?>">Size</a></th></tr> <?php $i=0; foreach ($dirs as $obj): ?> <tr class="r<?= $i++&1 ?>"><td class="folder"><a href="<?= $path,$obj,$term ?>"><?= $obj ?></a></td><td class="num">folder</td></tr> <?php endforeach; foreach ($files as $j=>$obj): ?> <tr class="r<?= $i++&1 ?>"><td class="file"><a href="<?= $path,$obj ?>"><?= $obj ?></a></td><td class="num"><?= $sizes[$j] ?> B</td></tr> <?php endforeach; ?> <tr><th colspan=2>Items: <?= $i ?> (files: <?= count($files) ?>, folders: <?= count($dirs) ?>)</th></tr> </table>
Запрос на подключение модуля:
INSERT INTO `site_categories` (`id`, `name`, `bits`) VALUES
('files', 'File Browser', 45);
Расшифровка значения поля bits (45=1011012):
- 102 – использовать режим подключения файлов x2 для подключения файла files.h.php с основным кодом модуля и файла вложенного шаблона files.php;
- 1 – разрешить GET-параметр p для непустых объектов категории;
- 1 – разрешить GET-параметр p для пустого объекта категории;
- 012 – использовать режим разрешений 1.
Демонстрация: /files – пробуем!
Исходники: g-drive-files-0.05.zip
Интересный модуль. Не для всех движков есть.