Название статьи конечно звучит громко, но на самом деле я расскажу лишь о базовой концепции создания файлового менеджера, а точнее редактора текстовых файлов (ну и конечно приведу несколько примеров и то что в итоге мы можем получить).
Поставим задачу. Мы хотим видеть страницу на которой будет располагаться древовидное представление нужной директории. Под данным деревом будет располагаться текстовый редактор. Должна быть возможность сохранить изменения в файле.
Так как велосипеды придумывать не нужно, то писать качественный текстовый редактор смысла нет (да и долго это будет). Поэтому воспользуемся готовым решением в виде PHP класса CKEditor.
Создадим php файл, подключим CKEditor и зададим шаблон страницы:
<?php
include_once( 'ckeditor/ckeditor.php' ) ;
$editor_name = "editor1";
$dog_path = "docs/";
if (!$_POST)
{
echo '<form action="" method="post">';
echo '<div style="height:250px;overflow:scroll;" id="fm"></div>';
echo '<div id="ed">;
$CKEditor = new CKEditor();
$CKEditor->editor($editor_name, "");
echo "<input type='hidden' name='act' value='edit' />";
echo '<input type="submit" value="Сохранить"/>';
echo '<div>';
echo '<form>';
}
else if ($_POST && isset($_POST["act"]))
{
/*
Так как у нас будет действие редактирования, то без запроса не обойтись,
Будем слать его на эту же страницу
*/
}
?>
Думаю данный шаблон в описании не нуждается, все достаточно понятно. Теперь нам нужно заполнить верхний div файлами и папками из каталога docs. Сделаем мы это с помощью функции, рекурсивной функции, описание которой ниже:
function dirTree($path, $level = 0) {
if (!is_dir($path)) { echo "Path is not dir!"; return; }
if (substr($path, -1) != "/") $path .= "/";
$d = opendir($path);
while (false !== ($filename = readdir($d)))
{
if ($filename == "." || $filename == "..") continue;
if (!is_dir($path.$filename))
{
for ($i = 0; $i < $level; ++$i) echo "-";
echo "<span onclick=\"LoadFile('".$path.$filename."');\"><input type='radio' value='".$path.$filename."' name='radio_file_sel' style='cursor:pointer;' />".$filename."</span>";
echo "<br/>";
}
else
{
echo "<b style='cursor:pointer;' onclick=\"var f = document.getElementById('".$level."_folder_".$filename."'); if (f.style.display=='block') f.style.display='none'; else f.style.display='block';\">".$filename."</b><br/>";
echo "<div id='".$level."_folder_".$filename."' style='display:none;'>";
dirTree($path.$filename, $level + 1);
echo "</div>";
}
}
closedir($d);
}
Данный код демонстрирует как можно вывести содержимое всех файлов и папок по указанному пути. Здесь стоит отметить несколько моментов:
1) Проверка if ($filename == «.» || $filename == «..»). Необходима так как PHP так же отображает путь текущего каталога (.) и путь каталога родителя (..);
2) for ($i = 0; $i < $level; ++$i) echo «-«;. Создает отступ для более красивого отображения каталогов и файлов.
3) После отображения папки, создается скрытый див, в котором отображается его содержимое путем рекурсивного вызова функции. За отображение\скрытие данного содержимого отвечает javascript.
4) В качестве значения каждого radio указывается полный путь к файлу. Это необходимо для сохранения отредактированного файла.
5) Скрипт LoadFile, который срабатывает при нажатии на файл, отвечает за загрузку содержимого файла в редактор. Реализовывать данный скрипт можно разными способами, поэтому рассматривать мы его не будем. Однако отметим, что за загрузку данных в редактор отвечает следующий код:
CKEDITOR.instances.[имя редатора].setData([текст]);
В нашем случае, при реализации скрипта inline (т.е. в файле php) код можно написать так:
var mytext = "текст из документа"; CKEDITOR.instances.<?php echo $editor_name; ?>.setData(mytext);
Объект CKEDITOR создается автоматически при создании формы редактора.
Теперь осталось только дописать сохранение изменений в файле. При нажатии кнопки сохранить, запрос уйдет на эту же страницу. Текст из редактора посылается в переменной с именем нашего редактора. Имя файла который нужно сохранить в переменной radio_file_sel.
Имеем:
if (file_exists($_POST["radio_file_sel"]))
{
$f = fopen($_POST["radio_file_sel"], "w+");
fwrite($f, $_POST[$editor_name]);
fclose($f);
echo "Файл '".$_POST["radio_file_sel"]."' успешно сохранен!
";
}
В итоге получаем картину:
<?php
include_once( 'ckeditor/ckeditor.php' ) ;
function dirTree($path, $level = 0) {
if (!is_dir($path)) { echo "Path is not dir!"; return; }
if (substr($path, -1) != "/") $path .= "/";
$d = opendir($path);
while (false !== ($filename = readdir($d)))
{
if ($filename == "." || $filename == "..") continue;
if (!is_dir($path.$filename))
{
for ($i = 0; $i < $level; ++$i) echo "-";
echo "<span onclick=\"LoadFile('".$path.$filename."');\"><input type='radio' value='".$path.$filename."' name='radio_file_sel' style='cursor:pointer;' />".$filename."</span>";
echo "<br/>";
}
else
{
echo "<b style='cursor:pointer;' onclick=\"var f = document.getElementById('".$level."_folder_".$filename."'); if (f.style.display=='block') f.style.display='none'; else f.style.display='block';\">".$filename."</b><br/>";
echo "<div id='".$level."_folder_".$filename."' style='display:none;'>";
dirTree($path.$filename, $level + 1);
echo "</div>";
}
}
closedir($d);
}
$editor_name = "editor1";
$dog_path = "docs/";
if (!$_POST)
{
?>
<script type='text/javascript>
function LoadFile(filename) {
var f = "";
//получаем в переменную f текст из файла filename, например ajax-ом
CKEDITOR.instances.<?php echo $editor_name; ?>.setData(f);
}
</script>
<?php
echo '<form action="" method="post">';
echo '<div style="height:250px;overflow:scroll;" id="fm">';
dirTree($dog_path);
echo '</div>';
echo '<div id="ed">;
$CKEditor = new CKEditor();
$CKEditor->editor($editor_name, "");
echo "<input type='hidden' name='act' value='edit' />";
echo '<input type="submit" value="Сохранить"/>';
echo '<div>';
echo '<form>';
}
else if ($_POST && isset($_POST["act"]))
{
if ($_POST["act"] == "edit")
{
if (file_exists($_POST["radio_file_sel"]))
{
$f = fopen($_POST["radio_file_sel"], "w+");
fwrite($f, $_POST[$editor_name]);
fclose($f);
echo "Файл '".$_POST["radio_file_sel"]."' успешно сохранен!
";
}
}
}
?>
Вот по сути и все. Теперь по аналогии можно добавить кнопки удаления файлов, создание нового файла. Для удобства можно заменить древовидное представление файлов более подходящим для Вашей задачи.