Первый сайт на PHP


 

ФАЙЛ ZAPROS.PHP

Сценарии этого файла запрашивают от посетителя дополнительную информацию для проведения действия. Начало сценария:

<html><?php

Сразу же выведем заголовок формы, общий для всех четырех вариантов запросов. В нем точно так же передадим выполняющему собственно действия сценарию на странице do.php имя текущей папки:

echo ("<form action=do.php?folder=$folder method=post>");

Бесспорно, можно было бы и не передавать имя текущей папки, а сообщать обработчику конкретные имена файлов, над которыми совершается действие, с полным путем к ним, однако так все-таки проще.

УДАЛЕНИЕ, ЗАПРОС ИНФОРМАЦИИ

Если на основной странице файлового менеджера - index.php - была нажата кнопка "Удалить", имя которой - "udal", то значение переменной $udal' в сценарии на странице-обработчике будет отличным от нуля (вернее, оно будет представлять собой значение атрибута value кнопки "Удалить" на основной странице -^собственно слово "Удалить"). Если была нажата какая-нибудь другая кнопка, то значение переменной $udal определено не будет. Поэтому для того, чтобы узнать, было ли посетителем выбрано в качестве желаемого действия удаление, проверим содержимое этой переменной:

if ($udal!="")

Выведем небольшое пояснение посетителю...

echo ("Удалить файлы?<bг>");

и список файлов, которые планируется удалить. Их список передан в форму в массиве $fl. В этот массив включены параметры value тех checkbox'oB, которые были отмечены посетителем на основной странице менеджера файлов перед тем, как нажать кнопку с названием действия (а в эти параметры, как вы наверняка помните, были помещены имена файлов и папок, отображавшихся на основной странице файлового менеджера - путь к ним передан через переменную Sfolder в адресной строке). Переберем все элементы массива $ f 1...

foreach ($fl as $i)
{

и выведем их значения - имена файлов, подлежащих удалению. Вместе с именем папки, в которой они расположены - его сценарий на этой странице получил через адресную строку.
Ну а для того, чтобы иметь возможность эти имена передать сценарию на следующей странице, выполняющему собственно действие,
Строго говоря, вместо имен переменных, равных именам элементов формы, обрабатываемой сценарием на этой странице, следовало бы использовать имена соответствующих элементов массивов SHTTP_POST_VARS[] и (в РНР начиная с версии 4.1) $_POST[]. Однако для более легкого понимания кода выбран первый вариант. При использовании настоящего сценария на практике вы можете сами заменить имена переменных на имена элементов упомянутых массивов.
рядом с каждым именем удаляемого файла поместим скрытое поле, в которое поместим это самое имя. Сценарию, выполняющему удаление, останется только совершить эту операцию над теми файлами, имена которых ему будут переданы.
Имя же папки, в которой эти файлы располагаются, передается сценарию - исполнителю действия через адресную строку, указанную в заголовке формы запроса информации - точно так же, как оно было передано данному сценарию, запрашивающему дополнительную информацию. Вы могли видеть этот заголовок несколькими абзацами выше.

Рис. 11.6. Удаление файлов и папок. Запрос подтверждения

Как и на первой странице, все эти скрытые поля сделаем массивом, для удобства - даже присвоим ему то же имя flf ]:

echo ("<input type=hidden name=fl[] value=$i>$i из папки $folder<br>");
}

И наконец, выведем кнопку, запускающую собственно удаление. Назовем ее точно так же, как и расположенную на основной странице - для единообразия:

echo ("<input type=submit value = \"Удалить" name=udal>");

В результате в том случае, если посетитель на основной странице отметит файлы и папки и нажмет кнопку "Удалить", то на странице запроса подтверждения (рис. 11.6) ему будет выдан список выбранных им файлов и предложено нажать одну из двух кнопок - "Удалить" или "Отмена" (код, выводящий последнюю, размещен в конце страницы -смотрите ниже).

КОПИРОВАНИЕ, ЗАПРОС ИНФОРМАЦИИ

Для того, чтобы произвести копирование файлов и папок из одной папки в другую, простого согласия пользователя на это действие мало. Нужно еще узнать, а в какую папку необходимо производить копирование.
А что нужно, чтобы это узнать? Необходимо выдать запрос на получение имени этой папки у пользователя. Можно, конечно, предоставить пользователю возможность просто ввести новый путь в поле ввода текста, как при использовании команды сору в командной строке MS-DOS. Но это представляется весьма неудобным. Лучше, наверное, вывести пользователю список всех имеющихся на его аккаунте папок, из которых он сможет выбрать нужную. Пометить имя каждой папки радиокнопкой (кружком из группы единственного выбора, см. рис. 11.1, 11.7) - и для выбора папки назначения копирования достаточно будет только ткнуть мышью в нужном месте).
Но как вывести список всех папок? Ведь они могут быть вложены друг в друга, так что простое сканирование корневой директории не поможет... А команд в нашем распоряжении для достижения данной цели не так и много. Считать список содержимого каталога, определить, является ли тот или иной элемент, содержащийся в каталоге, так же директорией, - вот, собственно, и все, что нам может предложить РНР.
И тут придет на помощь принцип рекурсии.
Под рекурсией понимается запуск программы из самой этой программы. Иными словами - вот программа запускается, исполняется, исполняется - а затем очередная команда представляет собой не что иное, как вызов этой самой программы! и вновь программа исполняется с начала, исполняется... и опять доходит до вызова самой программы, и опять исполняется с начала.
Разумеется, для того чтобы программа с рекурсией имела какой-то смысл, а не представляла из себя бесконечно повторяемые действия, на каком-то этапе данный процесс должен прерваться. Иными словами, запуск программы изнутри самой программы должен происходить не каждый раз при ее работе, а в зависимости от того, выполняется ли определенное условие. Естественно, рано или поздно в ходе работы программы условие должно перестать выполняться, и тогда рекурсия прервется - исходная программа изнутри нее самой запущена при невыполнении условия не будет.
Как же принцип рекурсии можно использовать для построения списка всех папок на аккаунте? А алгоритм построения этого списка при использовании рекурсии прост:

  • Получить список файлов и папок в текущей директории.
  • Перебирать элементы из этого списка по одному.
  • Если очередной элемент - директория, то вывести на страницу ее имя и выполнить этот алгоритм по отношению к этой директории, посчитав ее текущей.

Этот алгоритм следует реализовать в специальной функции - подпрограмме, которую можно вызывать по имени, передав ей при этом необходимую для работы информацию.
К данной последовательности действий можно сделать лишь одно дополнение: если в списке копируемых объектов есть папки, то из выводимого списка директорий должны быть исключены как сами эти папки, так и все вложенные в них. Данное требование довольно понятно - скопировать папку во вложенную в нее папку невозможно. Ну и, естественно, в список папок для копирования не должна попасть та папка, в которой копируемые файлы находятся - как можно файл скопировать сам на себя?
Остальные же действия кода, посвященного запросу подтверждения копирования файлов, те же самые, что и для кода удаления файлов и папок: вывести список копируемых объектов и кнопку подтверждения выбора действия.
Начало кода:

if ($copy!="")
{

Для удобства запишем в переменную название корневой папки аккаунта пользователя. Впоследствии мы будем ее неоднократно использовать в коде.

$begin="files";

Выводим запрос пользователю...

echo ("Объекты для копирования:<br>");

и, точно так же, как в блоке кода, посвященном удалению файлов, выводим список объектов, подлежащих копированию (сравните - код практически такой же):

foreach ($fl as $i)
{
echo ("<input type=hidden name=fl[] value=$i>$folder/$i<br>") ;

Еще один запрос...

echo ("<bг>Выберите папку для копирования :<br>") ;
и начинаем вывод дерева папок - вызываем функцию tree.
tree($begin);

РЕКУРСИВНАЯ ФУНКЦИЯ ВЫВОДА СПИСКА ДОСТУПНЫХ ДЛЯ КОПИРОВАНИЯ ПАПОК НА АККАУНТЕ

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

function tree($fId)

Поскольку в функции будут использоваться переменные еще и из других частей программы на странице, такие как Sfolder (путь к текущей папке) и массив $fl (список копируемых объектов; имена тех папок, что перечислены в нем, выводиться на страницу не будут, так как папку нельзя скопировать саму в себя или в свою же вложенную папку), то эти переменные необходимо объявить как глобальные в самой функции, указав их в ее начале после слова global:

global $folder; global $fl;

Комментарий:
Массив Sfl был передан сценарию запроса дополнительной информации с помощью формы на основной странице файлового менеджера — методом POST. Поэтому он также доступен через массив $HTTP_POST_VARS - как его элемент $HTTP_POST_VARS['fl'J (если в файле конфигурации РНР установлен в on параметр track_vars). Для использования этого массива в функции его надо также объявить глобальным - командой global $HTTP_POST_VARS;.

В РНР 4.1 версий и выше массив Sfl доступен и через массив $_POST. В отличие от $HTTPJPOST_VARS этот массив автоглобальный — т. е. для использования в функциях его элементов объявление самого массива в функциях производить не надо.
Если вы пожелаете заменить в рассматриваемой программе все вхождения переменной-массива Sfl на соответствующие им элементы массивов SHTTPPOSTVARS или SPOST, то помните, что последние нельзя для вставки их значений в строку указывать в тексте строки — для этого следует использовать оператор конкатенации (точку).
Начинаем сканировать папку, имя которой было передано в вызове функции, при помощи того же сценария, который мы уже неоднократно использовали, он разбирался еще в главе "Папкопотрошилка". При первом вызове функции ей передается имя корневой папки аккаунта, с нее функция и начинает свою работу.

$hdl=opendir($fld);
while ($file = readdir($hdl)) if ( ($file!=°.")&&($file!=".."))
Для удобства запишем полное имя - вместе с путем - очередного взятого из папки объекта в переменную $f llnm:
$fllnm=$fld."/".$file;

Если этот объект - тоже папка...

if (is_dir($fllnm)==True)

то выясним:

  • не является ли данная папка одновременно и объектом копирования? Если является - то, во-первых, в списке папок она появиться не должна - папку нельзя скопировать саму в себя, а, во-вторых, сканировать ее вложенные папки тоже незачем - копировать одну папку в другую, вложенную в нее, еще никому не удавалось;
  • не в этой ли самой папке находится копируемый файл? Если в этой же самой папке - то выводить ее имя бессмысленно: копирование файла на свое же место возможно, но никаких за собой последствий не влечет.

Для начала сравним полное имя (вместе с путем от корневой директории аккаунта) очередной найденной в сканируемой директории папки со всеми именами копируемых объектов (естественно, тоже полными). Если хоть одно такое имя совпадет с именем папки - то выводить имя этой папки в список доступных для копирования нельзя.

$по=0;
foreach ($fl as $i)
if ($fllnm==$folder."/".$i) $no=l;

Переменная $по примет значение 0, если совпадений не было, и 1, если были.

Комментарий:
Обратите внимание на способ фиксирования совпадения имен папок при их переборе - при помощи изменения значения ранее установленной переменной: в данном случае - $nо.
Используйте такой же способ, если вам надо узнать, произошло ли то или иное событие внутри какого-нибудь цикла - установите до цикла переменную в ноль, а внутри цикла в случае совершения события присвойте ей значение 1. Тогда после окончания цикла переменная будет равна 1, если событие произошло, и 0, если нет.

Итак - если очередная папка из сканируемой директории не является объектом копирования...

if ($no==0)

{ и эти объекты копирования расположены не в ней...

if ($fllnm!=$folder)

то ее имя можно вывести в качестве возможного пункта назначения копирования, снабдив его radio button - т. е. "кружком" для единственного выбора. (После отправки формы результат выбора окажется в переменной $rd в сценарии выполнения действия.)

echo ("<input name=rd type=radio value=$fllnm>$fllnm<br>");

Комментарий:
При отправке формы, содержащей radio buttons, сценарию-обработчику передается всего одна относящаяся к этим элементам формы переменная, имя которой совпадает с именем отмеченной radio button, а значением является содержимое параметра value отмеченной radio button.
При размещении в форме radio buttons им всем дается одно и то же имя — то имя, которое будет иметь в сценарии-обработчике переменная со значением выбранного radio button. Путаницы тут не будет — так как из всех radio buttons в форме отмеченным может быть только один элемент, то переменная в любом случае передастся всего одна.

То, что папка содержит копируемые файлы, является препятствием к выводу имени этой папки на экран как возможнего пункта назначения копирования. Но это отнюдь не значит, что в данной папке не должны сканироваться вложенные папки. Поэтому оператор i f определяет, не содержит ли рассматриваемая папка копируемых файлов, завершаем...

} и вот он - рекурсивный вызов функции tree:

tree ($fllnm);

Осталось закрыть все незавершенные операторы и циклы,

}
}
}
}

и "потрошимую" директорию.

closedir($hdl);

Функция вывода списка директорий,- пунктов назначения копирования завершена.
}
Работать она будет так. Изначально, как вы помните, функция вызывается с параметром Sbegin, именем корневой директории аккаунта. Функция сканирует эту директорию и, как только натыкается на вложенную папку, проверяет, можно ли ее сканировать, после чего, возможно, эта вложенная папка превращается в сканируемую. И опять: функция сканирует уже эту вложенную папку, и, если опять натыкается на папку, вложенную в эту вложенную папку, то начинает сканировать уже ее. И так продолжается до тех пор, пока функция не доберется до папки, где вложенных папок нет (согласитесь, что такая рано или поздно найдется). Дойдя до такой, функция возвращается на шаг назад и сканирует следующую вложенную папку. Если таковой не находит, то возврат идет дальше. Попробуйте себе все это представить - и сразу поймете, если еще не поняли.

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

Рис. 11.7. Копирование. Запрос папки назначения

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

if ($begin!=$folder) {
echo ("<brxinput name=rd type=radio value=$begin>$begin<br>");

и вывести кнопку запуска копирования.

echo ("<input type=submit value=\"Скопировать\" name=copy>");

Все.

}

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

ПЕРЕИМЕНОВАНИЕ, ЗАПРОС ИНФОРМАЦИИ

Для переименования файла нужно узнать у пользователя новое имя для этого файла. Именно это и делает выводимая нижеследующим сценарием на страницу форма. Однако сценарию-обработчику данной формы необходимо передать как старое имя файла, так и новое, чтобы ему было понятно, какой файл необходимо переименовывать.
Если на основной странице была нажата кнопка "Переименовать"...

if ($ren!="") { то выведем пояснение пользователю...
echo ("Переименовать файлы?<bг>");

и для каждого файла или папки, чье имя было отмечено в соответствующем checkbox'e на главной странице...

foreach ($fl as $i)
{

поместим в форму скрытое поле, в котором запишем старое имя файла. Сценарию-обработчику ведь надо знать, какой файл переименовывать?

echo ("<input type=hidden name=afl[] value=$i>");

Выведем старое имя файла...

echo ("$i");

и текстовое поле для ввода нового имени. Для удобства поместим в это текстовое поле старое имя - если пользователю надо было его изменить совсем немного, то ему сделать это будет легче.

echo ("<input type=text size=30 name=rfl[] value=$ixbr>") ;

Такие поля выведем для каждого файла или папки, подлежащего переименованию.
}
И выведем кнопку, запускающую процесс переименования путем перехода на страницу со сценарием-обработчиком с передачей этому сценарию отличного от пустой строки значения переменной $rеn:

echo ("<input type=submit value=\"Переименовать\" name=ren>");

Блок запроса дополнительной информации по переименованию файлов или папок закончен.
}
В результате работы данного сценария (а это произойдет только в том случае, если на основной странице файлового менеджера была нажата кнопка "Переименовать") посетителю будет отображен список выбранных им для переименования файлов, для каждого из которых он сможет ввести новое имя (рис. 11.8)
После нажатия кнопки "Переименовать" на странице запроса дополнительной информации сценарию-исполнителю действия будут переданы два массива - $afl и $rfl - со старыми и новыми именами файлов и папок, причем их элементы, относящиеся к одному и тому же файлу или папке, будут иметь один и тот же порядковый номер.
Полные же пути к переименовываемым файлам и папкам сценарий сможет восстановить на основе значения переменной Sfolder, переданной ему в ссылке на страницу со сценарием-обработчиком, указанной в заголовке формы (см. ранее).

Рис. 11.8. Переименование. Запрос новых имен

СОЗДАНИЕ НОВОЙ ПАПКИ, ЗАПРОС ИНФОРМАЦИИ

Для создания новой папки нужно получить от пользователя всего одно слово - имя этой самой новой папки.
Если на основной странице файлового менеджера было выбрано действие "Создание папки"...

if ($md!="")

то выведем на страницу поле для его ввода (его содержимое передастся сценарию-обработчику в переменной Snewname):

echo ("Введите имя папки: <brxinput type=text size=30 name=newname>");

и кнопку, запускающую это самое создание:

echo ("<input type=submit value=\"Создать папку \ " name=md>");

Собственно, и все.

}
?>

Посетитель увидит поле ввода для имени новой папки (рис. 11.9)

Рис. 11.9. Создание новой папки. Поле ввода ее имени

КНОПКА ОТМЕНЫ

Для того, чтобы со страницы запроса информации можно было уйти без последствий, если посетитель передумает что-либо делать со своими файлами, поместим на эту страницу кнопку "Отмена" (см. рис. 11.6-11.9):

<brxinput type=submit value="OTMeHa" name=otmena>

Собственно, это и есть весь текст этой страницы:

</form></html>

Графическое оформление - уже на вкус сайтостроителя.

 
Назад Начало Вперед