Материалов по теме "Как создать собственный фильтр для шаблонов Template Toolkit" достаточно, как на русском, так и на английском языках.
А вот примеров кода реально работающего фильтра практически нет. Восполняю этот пробел, возможно кому-нибудь пригодится.
Далее изложено 3 варианта создания фильтра, все - работающие. Разъяснений и комментариев в этот раз не будет. Для изучения теории создания шаблонов рекомендую несколько публикаций, ссылки на которые приведены в заключительной части.
Варианты кода для создания фильтра
Примеры разработаны для решения задачи:
Есть строка текста неопределенной длины. Надо эту строку сократить до определенного администратором числа символов.
Вариант 1. Самый простой
1) В модуле, где происходит создание объекта шаблона, создать подпрограмму-фильтр.
Например:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$MAX_LENGTH = 30; sub filter { my $text = shift; if (length($text) > $MAX_LENGTH) { ... # обработка переменной $text регулярными выражениями, # формирование ее нового значения ... } return $text; } |
Фильтр, в данном случае, выполняет следующие действия: принимает данные для обработки, проводит обработку, возвращает измененные данные. В общем, это самая обыкновенная функция.
Кстати, можно разместить фильтр в другом модуле, а потом его просто подключить с помощью use.
2) В опции, которые задаются при создании объекта TemplateToolkit, добавляем параметр FILTERS.
Пример:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
... my $template_options = { ... INCLUDE_PATH => $templ_path, FILTERS => { 'new_filter' => \&filter, }, ... }; my $template = Template->new($template_options) || do { $ERROR = "Can't create Template object: ".$Template::ERROR; return undef; }; ... |
3) Фильтр создан и его можно использовать в шаблонах Template Toolkit, как любой другой фильтр:
|
1 |
[%- 'очень_длинная_фраза_которую_надо_укоротить' | new_filter -%] |
Вариант 2
Создаем фильтр в виде подключаемого в шаблонах плагина.
1) Создаем плагин.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package Template_Plugin::MyNewFilter; use Template::Plugin::Filter; use base qw( Template::Plugin::Filter ); use vars qw( $FIRST_PART_LENGTH $LAST_PART_LENGTH $MAX_LENGTH ); $FIRST_PART_LENGTH = 15; $LAST_PART_LENGTH = 7; $MAX_LENGTH = 30; sub filter { my ($self, $text) = @_; if (length($text) > $MAX_LENGTH) { $text =~ /^(.{$FIRST_PART_LENGTH}).+(.{$LAST_PART_LENGTH})$/i; $text = $1.'...'.$2; } return $text; } 1; |
2) Плагин-фильтр должен располагаться пространстве имен, которое задается опциями, при создании объектов Template Toolkit.
|
1 2 3 4 5 6 7 8 9 10 |
... my $template_options = { ... PLUGIN_BASE => $TTPluginBase, ... }; my $template = Template->new($template_options) || do {$ERROR = "Can't create Template object: ".$Template::ERROR; return undef;}; ... |
3) Используем получившийся плагин в шаблонах Template Toolkit.
|
1 2 3 4 |
[%- USE MyNewFilter -%] [% FILTER $MyNewFilter %]очень_длинное_название_продукта_ которое_не_помещается_в_одной_строке[% END %] |
Вариант 3. Самый правильный
Не знаю, как Вам, но мне не нравится указывать в шаблонах фильтр, с помощью знака доллара: FILTER $MyNewFilter . Если уж добавлять фильтр, как плагин, то и использовать, как обычный стандартный
фильтр: FILTER MyNewFilter.
Поэтому, продолжаем поиски. И находим третий вариант создания фильтра.
1) Создаем модуль плагина-фильтра:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
package Template_Plugin::MyNewFilter; use strict; use Template::Plugin::Filter; use base qw( Template::Plugin::Filter ); use vars qw( $FIRST_PART_LENGTH $LAST_PART_LENGTH $MAX_LENGTH ); $FIRST_PART_LENGTH = 15; $LAST_PART_LENGTH = 5; $MAX_LENGTH = 30; sub new { my ($class, $context, @params) = @_; my $self = { _CONTEXT => $context, _DYNAMIC => 1, }; bless $self, $class; $self->install_filter('MyNewFilter'); return $self; } sub filter { my ($self, $text) = @_; if (length($text) > $MAX_LENGTH) { $text =~ /^(.{$FIRST_PART_LENGTH}).+(.{$LAST_PART_LENGTH})$/i; $text = $1.'...'.$2; } return $text; } 1; |
Стоит отметить, что метод install_filter предлагают использовать многие руководства по Template::Plugin::Filter, однако ни одно из них даже словом не упоминает, что необходимо создавать метод new, а так же - как его создавать. А без new стабильно работать будет только 500-ая ошибка сервера.
2) Не забываем, что плагин-фильтр должен быть размещен в определенном опцией PLUGIN_BASE пространстве имен.
3) Вот оно счастье - красивое использование фильтра:
|
1 2 3 4 |
[%- USE MyNewFilter -%] [%- 'это-название-ни-в-какие-рамки-не-лезет' FILTER MyNewFilter -%] или [%- 'это-название-ни-в-какие-рамки-не-лезет' | MyNewFilter -%] |
Полезные ссылки
Разнообразные теоретические аспекты создания фильтров можно узнать по приведенным ниже адресам:
http://www.template-toolkit.ru/Modules/Template/Plugin/Filter.html
http://www.template-toolkit.ru/Modules/Template/Plugin.html
http://search.cpan.org/~abw/Template-Toolkit-2.22/lib/Template/Plugin/Filter.pm
Книга: Perl Template Toolkit - O'Reilly - By Darren Chamberlain, David Cross, Andy Wardley