PHP+JS: Файловый менеджер

Название статьи конечно звучит громко, но на самом деле я расскажу лишь о базовой концепции создания файлового менеджера, а точнее редактора текстовых файлов (ну и конечно приведу несколько примеров и то что в итоге мы можем получить).

Поставим задачу. Мы хотим видеть страницу на которой будет располагаться древовидное представление нужной директории. Под данным деревом будет располагаться текстовый редактор. Должна быть возможность сохранить изменения в файле.

Так как велосипеды придумывать не нужно, то писать качественный текстовый редактор смысла нет (да и долго это будет). Поэтому воспользуемся готовым решением в виде 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"]."' успешно сохранен!
"; } } } ?>

Вот по сути и все. Теперь по аналогии можно добавить кнопки удаления файлов, создание нового файла. Для удобства можно заменить древовидное представление файлов более подходящим для Вашей задачи.

Запись опубликована в рубрике JavaScript, PHP с метками , , , , . Добавьте в закладки постоянную ссылку.