Чтобы создать свой собственный фильтр, вы должны создать свой собственный класс, имеющий тип WactCompilerFilter (limb/wact/src/compiler/filter/WactCompilerFilter.class.php).
Файл вашего нового класса должен быть расположен в одной из директорий вида src/template/tags и иметь имя some_filter_name.filter.php. Обратите внимание на окончание .filter.php.
Рассмотрим пример простого фильтра, выполняющего операцию заключения строки в кавычки. Назовем нам фильтр QuoteFilter. В шаблоне мы предполагаем использовать синтаксис {$var|quote}.
Пример шаблона:
{$'A String'|quote}
За компиляцию константных значений отвечает метод getValue() фильтра. В нашем случае это будет:
function getValue() { if ($this->isConstant()) { return quote($this->base->getValue()); } else { RaiseError('compiler', 'UNRESOLVED_BINDING'); } }
(Здесь и далее мы подразумеваем, что функция quote($string) уже определена)
WACT компилирует такие шаблоны в полностью статический код, то есть в скомпилированном шаблоне вы получите следующее:
"A string"
Любой фильтр содержит ссылку на так называемую базу $base. $base - это обычно объект класса WactExpression или же WactDataBindingExpression, в зависимости от того, является ли база контстантным значением или же ее значение не может быть определено на этапе компиляции. В принципе, если к выражению применена целая цепочка фильтров (несколько фильтров сразу), то базой может быть другой фильтр.
База, впрочем как и параметры фильтров (см. ниже) поддерживают следующий набор методов:
Фильтр считается константным, если его база и все его параметры также являются статическими. Только в этом случае будет вызван метод getValue() для фильтра.
Пример шаблона:
{$variable|quote}
За компиляцию динамических значений отвечает метод generateExpression($code_writer) фильтра.
$code_writer - это экземпляр класса WactCodeWriter, который мы упоминали в разделе "Как работает компилятор WACT-шаблонов".
В нашем случае это будет:
function generateExpression($code_writer) { $code_writer->writePHP('quote('); $this->base->generateExpression($code_writer); $code_writer->writePHP(')'); }
WACT компилирует такие шаблоны в «динамический» код, то есть в скомпилированном шаблоне фильтр применяется «на лету».
Обратите внимание, что последний $code_writer→writePHP(')'); не содержит завершающей точки и запятой, так как фильтр может быть частью длинной цепочки.
Для начала давайте выясним, зачем это вообще нужно? Ведь, казалось бы, при компиляции в «статику» мы получаем только экономию - на вызове той или иной функции (функций). Однако, может возникнуть ситуация, в которой функция будет возвращать свой результат в зависимости от некоего контекста. В нашем случае: возможно, при смене локали мы захотим применять другие кавычки. В таком случае нашему фильтру нужно будет «подменить» метод isConstant() родительского класса:
function isConstant() { return false; }
Таким образом мы сообщаем компилятору WACT, что значение, которое проходит через фильтр - не константа и для него нужно сгенерировать код посредством generateExpression(). Если мы воспользуемся таким подходом, метод getValue() становится в нашем фильтре не нужен и его можно смело удалить!
Полный код получившегося фильтра будет выглядеть следующим образом:
/** * @filter quote */ class QuoteFilter extends WactCompilerFilter { function isConstant() { return false; } function generateExpression($code_writer) { $code_writer->writePHP('quote(('); $this->base->generateExpression($code_writer); $code_writer->writePHP(')'); } }
Как видите, кроме самого кода класса фильтра, здесь имеется также мета-код регистрации нового фильтра в Словаре Фильтров WACT. В нашем случае это мета-тег @filter, которое указывает на имя фильтра, которое вы будете использовать в своих шаблонах.
Обратите внимание на использование следующего фрагмента кода в файле нашего QuoteFilter:
/** * @filter quote */
Это так называемые аннотации. По этим аннотациям словарь фильтров формирует свое содержимое. Подробнее о словарях в разделе "Словари элементов WACT-шаблона".
Полный список аннотация для фильтров:
Если максимальное и минимальное количество параметров фильтра не указано, соответствующие проверки не делаются.
Фильтры могут принимать дополнительный параметры, которые в шаблоне следуют за названием фильтра и знака двоеточия, например, {$var|trim:«&»}. «&» - это параметр фильтра trim.
Параметры доступны в классе фильтра в виде атрибута $parameters.
Рассмотрим код класса WactTrimFilter:
<?php /** * @filter trim * @max_attributes 1 */ class WactTrimFilter extends WactCompilerFilter { function getValue() { if(isset($this->parameters[0]) && $this->parameters[0]->getValue()) $characters = $this->parameters[0]->getValue(); else $characters = ''; if (!$this->isConstant()) $this->raiseUnresolvedBindingError(); if($characters) return trim($this->base->getValue(), $characters); else return trim($this->base->getValue()); } function generateExpression($code) { $code->writePHP('trim('); $this->base->generateExpression($code); if(isset($this->parameters[0]) && $this->parameters[0]->getValue()) { $code->writePHP(','); $this->parameters[0]->generateExpression($code); } $code->writePHP(')'); } } ?>
Параметры не имеют имен, поэтому приходится их получать по индексу.
Параметры поддерживают тот же самый набор методов, что и база.
Обсуждение