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

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

Функции передается один параметр - имя папки, список вложен­ных папок в которой она должна выдать.

function tree($fId) {

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

функции, указав их в ее начале после слова global: global $folder; global $f1; Комментарнй:

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

В РНР 4.1 версий и выше массив $fl доступен и через массив SJPOST. В отличие от $HTTP_POST__VARS этот массив автогло­бальный - т. е. для использования в функциях его элементов объявле­ние самого массива в функциях производить не надо.

Если вы пожелаете заменить в рассматриваемой программе все вхождения переменной-массива $fl на соответствующие им элемен­ты массивов $ HTTP POST_ VARS или SPOST, то помните, что по­следние нельзя для вставки их значений в строку указывать в тексте строки - для этого следует использовать оператор конкатенации (точку).

Начинаем сканировать папку, имя которой было передано в вызове функции, при помощи того же сценария, который мы уже неоднократ­но использовали, он разбирался еще в главе "Папкопотрошилка". При первом вызове функции ей передается имя корневой папки аккаунта, с нее функция и начинает свою работу.

$hdl=opendir($fId);

while ($file = readdir($hdl)) {

if  (($file!=".")&&{$file!="..")) {

Для удобства запишем полное имя - вместе с путем - очередного взятого из папки объекта в переменную $f 11 run:

$fllnm=$fld."/".$file;

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

if  (is_dir($fllnm)==True)

{

то выясним:

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

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

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

$по=0;

foreach ($fl as $i)

{

if  ($fllnm==$folder."/"-$i) {

$no=l;

}

}

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

Комментарий:

Обратите внимание на способ фиксирования совпадения имен па­пок при их переборе - при помощи изменения значения ранее установ­ленной переменной: в данном случае - $по.

Используйте такой же способ, если вам надо узнать, произошло ли то или иное событие внутри какого-нибудь цикла - установите до цикла переменную в ноль, а внутри цикла в случае совершения события присвойте ей значение 1. Тогда после окончания цикла переменная бу­дет равна 1, если событие произошло, и 0, если нет.

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

if ($по==0) {

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

if ($fllnm!=$folder) {

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

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

Комментарий:

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

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

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

}

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

tree  ($fllnm);

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

}

}

}

}

и "потрошимую" директорию, closedir($hdl);

Функция вывода списка директорий - пунктов назначения копиро­вания завершена.

}

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

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

 

<ht»l>

<form асеion-do. Куда копировать <brxinput type-

<br><lnpuc type-

<b г Xb г > Выверите <br><Input name-files/ Folder 1 <br><input <br><input

<brx input

<br><input </html>

 

name name type type

php?folder-flles/FolderZ mechod-post> файлы?

hidden name-£l[] value«page4.php>files/Folder2/page4.php

hidden name-£l[] value«page5.php>files/Folder2/page5.php папку для копирования:

rd type-radio vaiue-files/Folderi>

rd type-radio value*files/Folder2/Folder3>£iles/Folder2/Folder3 rd type-radio value-files>£iles

submit value-''Скопировать" name-copy> submit value-"Отмена" aamaotx/form>|

-KpiM/>apt4>f»4>tip?foltlfT hlr«;."folder?  Міслж>& fM*£jftt6tj

 

Куда копировать файлы? file s/Folder2/p age4 .php files/Folder2/page5.php

Выберите папку для копирования: С ffles/F older 1 6 files/Folder2/Folder3 с files

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

if   ($begin!=$folder) {

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

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

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

Все.

}

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