camel
Модуль HTML::Phl
Для обработки HTML-документов, содержащих инструкции с кодом Perl
О модуле Спецификация Downloads Контакты

Функции  

В PHL добавлена всего одна функция 'include()', реализованная для возможности сборки документа из нескольких файлов, содержащих HTML (TXT) или PHL разметку.

Функция 'include()' похожа на стандартную Perl функцию 'open()', с тем отличием, что первым аргументом является имя включаемого в документ файла, а вторым - один или несколько специальных управляющих параметров.


 1 %pl include($file_name);
 2    
 3 <%pl include("$file_name", "socket"); %>
 4 
 5 <%pl
 6    my $result = include("$file_name", "open decode");
 7 %>

В общем случае, написание функции 'include()' выглядит так:


include("file_name" [, "param" [, "name_process"]]);


file_name : "file_name.phl"
            "file_name.cgi"
            "file_path/file_name.phl"
            "/file_path/file_name.html"
            "http://domain/file_path/file_name.html"

[param] :
          phl        <=>  phl
          exist      <=>  ex
          head       <=>  hd
          abs        <=>  abs  
          no_abs     <=>  na   
          no_eval    <=>  ne   
          no_strict  <=>  ns   
          open       <=>  on   
          decode     <=>  dc  
          no_decode  <=>  nd   
          cgi        <=>  cgi  
          socket     <=>  sk   
          fork       <=>  fk   
          thread     <=>  td   

зависимости :
          phl [.phl] <= exist, head, abs, decode
          cgi [.cgi] <= require, decode
          open       <= decode, abs
          socket     <= exist, head, no_abs, decode, no_decode
          fork       <= waitpid, no_waitpid
          thread     <= join, detach


Первый аргумент 'file_name' кроме имени файла может содержать зарезервированные слова "JOIN", "CONFIG" или "TIMER".

Если файл 'file_name' имеет расширение '.phl', то такой файл идентифицируется, как файл формата PHL. Расширение может быть изменено в настройках с помощью $phl{pl}.

При вызове функции 'include()' в неопределенном контексте результат выполнения кода Perl помещается в тело документа внутри функции print().

При скалярном или списковом контексте результат возвращается в виде запрашиваемого значения переменной или списка значений соответственно.


 1 <%pl
 2    include("file_name.phl");
 3    my $result = include("file_name.phl");
 4    my @result = include("file_name.phl");
 5 %>

Второй аргумент функции 'include()' может содержать один или несколько специальных управляющих параметров.


• Параметр 'phl'

Данный параметр указывает обработчику, что код, содержащийся в подключаемом файле, представляет собой документ формата PHL.

Данные файла отправляются в анализатор, где преобразуются в perl-код и передаются 'eval'.

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


 1 <%pl
 2    include("file_name.txt", "phl");
 3    my $result = include("file_name.html", "phl decode=utf-8");
 4    my @result = include("file_name", "phl abs");
 5 %>

• Параметр 'exist' ('ex')

Позволяет проверить существование файла.


 1 <%pl
 2    my $exist_file = include("$file_name", "exist");
 3    if ($exist_file) {
 4       print "Файл $file_name найден";
 5    } else {
 6       print "Файл $file_name не найден";
 7    }
 8 %>

• Параметр 'head' ('hd')

Возвращает список из 5 элементов: Content type, Document length, Modified time, Expires, Server.


 1 <%pl
 2    my @head = include("$file_name", "head");
 3 %>

• Параметр 'abs'

Если указан параметр 'abs', осуществляется преобразование относительных ссылок, указанных в файле, в абсолютные.


 1    %pl include("$file_name", "abs");

• Параметр 'no_eval' ('ne')

При указании данного параметра результат выполнения кода включаемого файла игнорируется.


 1 <%pl include("$file_name", "no_eval") %>

• Параметр 'no_strict' ('ns')

Если указан параметр 'no_strict', то на код загружаемого файла '$file_name' действие прагмы 'use strict' не распространяется.


 1 <%pl
 2    include("$file_name", "ns");
 3 %>

• Параметр 'open' ( 'on' )

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


 1 <%pl
 2    include("$file_name", "open");
 3    my $result = include("$file_name", "open decode=koi8-r");
 4    my @result = include("$file_name", "on, decode=cp1251, abs");
 5 %>

В скалярном или неопределённом контексте данные считываются "побайтно":


 1    my $code;
 2    open(my $fh, "<$file_name");
 3       while (sysread($fh, my $bate, 8*1024)) {
 4          $code .= $bate;
 5       }
 6    close($fh);

В списковом контексте данные файла считываются построчно:


 1    open(my $fh, "$file_name");
 2       flock($fh, 1);
 3       @result = <$fh>;
 4    close($fh);

• Параметр 'decode' ('dc')

При наличии параметра 'decode' данные из указанной в параметрах кодировки (к примеру, 'decode=cp1251') декодируются во внутренний формат Perl.

Если кодировка не указана или отсутствует параметр 'decode', то при декодировании подразумевается, что кодировка включаемого файла соответствует $phl{encoding_in}, указанной в настройках phl.pm (или config.phl).


 1    $_ = decode($decode, $_);
 2    $_ = decode($phl{encoding_in}, $_);

Если кодировка результирующего документа отлична от 'utf-8', то дополнительно осуществляется кодирование данных в кодировку $phl{encoding_out}, указанную в настройках phl.pm (или config.phl).


 1    $_ = encode($phl{encoding_out}, $_);

Кодирование и декодирование данных осуществляется с использованием стандартного модуля 'Encode.pm'.


• Параметр 'cgi'

Данный параметр предназначен для подключения cgi-скриптов, написанных на Perl.


 1 <%pl
 2    include("file_name.cgi");
 3    include("$file_name", "cgi");
 4    include("$file_name", "cgi require");  
 5    include("file_name.cgi", "decode=cp866");
 6 %>

Совместно с параметром 'cgi' могут применяться дополнительные параметры 'decode', 'require'.

○ параметр 'decode' ('dc')

Служит для декодирования cgi-скриптов Perl, написанных не в UTF-8 кодировке.

○ параметр 'require' ('rq')

Указывает на подключение cgi-скриптов с помощью стандартной функции 'require'

.
 1    require "$file_name";


• Параметр 'socket' ('sk')

Применяется для загрузки web-документа с помощью стандартного модуля 'IO::Socket::INET'


 1 <%pl
 2    include("file_name.html", "socket");
 3    include("http://domain/");
 4    my $text = include("http://domain/file_path/file_name.html", "decode=cp1251");
 5    my @result = include("$file_name", "decode no_abs");
 6 %>

Если адрес включаемого в документ файла начинается с http или ftp, то указывать параметр 'socket' не обязательно.

Совместно с параметром 'socket' могут применяться дополнительные параметры 'exist', 'head', 'no_abs', 'decode', 'no_decode'.

○ параметр 'exist' ('ex')

Позволяет проверить существование домена, файла, адреса.


 1 <%pl
 2   my @include_name_file = (
 3     'dir1/name_file.html',
 4     '/dir2/name_file.php',
 5     'http://www.yandex.ru',
 6     'http://www.yandex/eklmnfjoeqxngsitwf.html',
 7     'http://eklmnfjoeqxngsitwfhoevd.ru'
 8   );
 9  
 10   foreach my $name_file (@include_name_file) {
 11     my $ex = include("$name_file", "socket exist");
 12     if ($ex) {
 13        print "Файл '$name_file' найден<br>";
 14     } elsif (!defined $ex) {
 15        print "Ресурс '$name_file' не отвечает<br>";   
 16     } else {
 17        print "Файл '$name_file' не найден<br>";
 18     }
 19   }
 20 %>

○ параметр 'head' ('hd')

Возвращает заголовок документа


 1 <%pl
 2   foreach my $name_file (@test_name_file) {
 3     my @head = include("$name_file", "socket head");
 4     if ($#head) {
 5        print "Заголовок от '$name_file' получен => '@head[0..3]'<br>";
 6     } else {
 7        print "Заголовка от '$name_file' нет => '@head'<br>";
 8     }
 9   }
 10 %>

○ параметр 'no_abs' ('na')

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


 1 %pl include("$file_name", "socket no_abs");

○ параметр 'decode' ('dc')

Служит для декодирования документов из кодировки, указанной параметром 'decode', во внутренний формат Perl и далее в кодировку, указанную в настройках в $phl{encoding_out}.

Если параметр 'decode' используется без указания исходной кодировки запрашиваемого файла, то декодирование осуществляется с учетом кодировки, указанной в заголовке файла в 'charset' (при наличии).

Если параметр 'decode' не используется, по умолчанию подразумевается, что наш файл в кодировке utf-8.

При использовании параметра 'no_decode' ('nd') никакого декодирования данных не происходит.


 1 <%pl
 2    include("http://www.rbc.ru", "decode=utf-8");
 3    include("http://www.mail.ru", "decode");
 4    my $html_text1 = include("http://ru.motorsport.com");
 5    my $html_text2 = include("http://www.google.com", "nd");
 6 %>

• Параметр 'fork' ('fk')

Код загружаемого файла выполняется в параллельном дочернем процессе, созданном в результате запуска 'fork()'.


 1 <%pl
 2    include("$file_name", "fork");
 3 %>

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


 1 <%pl
 2    # Код дочернего процесса $phl_var{name}
 3    my $f = "Передаваемые данные";
 4    sleep 1;
 5    return $f;
 6 %>

В третьем аргументе функции 'include()' можно указать уникальное имя дочернего процесса, чтобы затем обратиться за результатом выполнения дочернего процесса "по имени".


 1 <%pl
 2    include("$file_name", "fork", "f1");
 3 %>

○ параметр 'waitpid' ('wd')

Для того, чтобы вернуть результат выполнения дочернего процесса в точку вызова функции 'include()', необходимо дополнительно к параметру 'fork' указать параметр 'waitpid' или в качестве третьего аргумента функции 'include()' указать 'waitpid'.

Результат отработки параллельного процесса можно вернуть обратно в родительский процесс, вызвав 'include()' в скалярном или списковом контексте.


 1 <%pl
 2    $result = include("$file_name", "fork waitpid");
 3    @result = include("$file_name", "fork", "waitpid");
 4 %>

На самом деле, можно вообще отказаться от параметра 'waitpid', как во втором так и в третьем аргументе. В таком случае, программа всё равно будет ждать завершения дочернего процесса, а функция 'include()' получается менее громоздкой.


 1 <%pl
 2    @result = include("$file_name", "fork", "");
 3    $result = include("$file_name", "fk");
 4 %>

○ параметр 'no_waitpid' ('nw')

Результат выполнения процесса вернуть не удастся, если только, не попробовать что-либо записать в файл или вывести на экран.


 1 <%pl
 2    include("$file_name", "fork no_waitpid");
 3    include("$file_name", "fork", "no_waitpid");
 4 %>

○ аргумент 'JOIN'

Для обращения за результатом выполнения дочернего процесса можно использовать функцию 'include()', где в качестве первого аргумента необходимо указать зарезервированное слово 'JOIN', вторым аргументом - имя или имена дочерних процессов.


 1 <%pl
 2    include("$file_name", "fork", "f1");
 3   
 4    # Далее может следовать тело программы с некоторым кодом
 5 
 6    my $rezult = include("JOIN", "f1");
 7 %>

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


 1 <%pl
 2    my %join_2_3 = include("JOIN", "f2 f3"); 
 3    print "Результат процесса 'f2' = $join_2_3{f2}<br>";
 4 
 5    my %join_all = include("JOIN");
 6    foreach my $key(keys(%join_all)) {
 7       if (ref $join_all{$key}) {
 8          my @result = @{$join_all{$key}};
 9          print "Результат процесса '$key' = '$join_all{$key}' => и первый разыменованный элемент массива = '$result[0]'<br>";
 10       } else {
 11          print "Результат процесса '$key' = '$join_all{$key}'<br>";
 12       }
 13    }
 14 %>

• Параметр 'thread' ('td')

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

Для создания нити используется стандартный модуль 'thread' (в свою очередь, Perl должен быть настроен на работу с тредами).


 1 <%pl
 2    include("$file_name", "thread");
 3 %>

Как и в случае с параметром 'fork', при использовании нитей существует возможность вернуть результат выполнения созданной нити, как в точку вызова функции 'include()', так и в произвольную точку программы или вообще "забыть" о результате, ничего не возвращая.

○ параметр 'join' ('jn')

Результат выполнения нити возвращается в точку вызова, при этом родительский процесс временно прекращает своё выполнение и ждет получения данных (от созданных потоков).


 1 <%pl
 2    $result = include("$file_name", "thread join");
 3    @result = include("$file_name", "thread", "join");
 4    %result = include("$file_name", "thread");
 5 %>

○ параметр 'detach' ('dh')

Нить создается, но что в ней происходит основная ветка процесса не знает.


 1 <%pl
 2    include("$file_name", "thread detach");
 3    include("$file_name", "thread", "detach");
 4 %>

Вернуть данные в любую точку основной ветки процесса можно, присвоив нити имя (по аналогии с дочерним процессом, создаваемым параметром 'fork').


 1 <%pl
 2    include("$file_name", "thread", "t1");
 3    include("$file_name", "thread", "t2");
 4    include("$file_name", "thread", "t3");
 5   
 6    my $rezult = include("JOIN", "t2");
 7    print "Результат нити 't2' = '$rezult'<br>";
 8 
 9    my %join = include("JOIN", "t1 t3"); 
 10    print "Результат нити 't1' = '$join{t1}'<br>";
 11    print "Результат нити 't3' = '$join{t3}'<br>";
 12 %>

• Дополнительные параметры

При желании можно определить свои собственные (дополнительные) параметры или переопределить существующие. Это реализуется с помощью специально оформленных модулей.

Так, к примеру, с помощью модуля 'HTML::Phl::Utilit' и параметра 'analys' ('as') появляется возможность просмотреть сформированный анализатором код perl включаемого файла перед его выполнением eval.

пример:

 1 %pl -ev use HTML::Phl::Utilit;
 2 
 3 <%pl
 4    include("$file_name", "as");
 5 %>




22232