Инструменты пользователя

Инструменты сайта


limb3:ru:packages:wact:how_to_create_new_filter

Создание собственных фильтров WACT

Чтобы создать свой собственный фильтр, вы должны создать свой собственный класс, имеющий тип 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, в зависимости от того, является ли база контстантным значением или же ее значение не может быть определено на этапе компиляции. В принципе, если к выражению применена целая цепочка фильтров (несколько фильтров сразу), то базой может быть другой фильтр.

База, впрочем как и параметры фильтров (см. ниже) поддерживают следующий набор методов:

  • isConstant() - возвращает true, если параметр - статический.
  • getValue() - возвращает значение статического параметра или генерит ошибку для динамического параметра.
  • generatePreStatement($code_writer) - генерит код, необходимый для получения контейнера данных, из которого можно взять значение параметра на этапе выполнения шаблона.
  • generateExpression($code_writer) - генерит код получающий значение параметра из контейнера данных.
  • generatePostStatement($code_writer) - генерит завершающий код (реально редко не используется).

Фильтр считается константным, если его база и все его параметры также являются статическими. Только в этом случае будет вызван метод 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-шаблона".

Полный список аннотация для фильтров:

  • filter - название фильтра, которое используется в шаблоне.
  • min_attributes - минимальное количество параметров фильтра (о параметрах чуть ниже).
  • max_attributes - максимальное количество параметров фильтра.

Если максимальное и минимальное количество параметров фильтра не указано, соответствующие проверки не делаются.

Параметры фильтров

Фильтры могут принимать дополнительный параметры, которые в шаблоне следуют за названием фильтра и знака двоеточия, например, {$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(')');
  }
}
?>

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

Параметры поддерживают тот же самый набор методов, что и база.

Обсуждение

Ваш комментарий. Вики-синтаксис разрешён:
   __ __   __    ____   ___   _____
  / // /  / /   / __/  / _ | / ___/
 / _  /  / /__ _\ \   / __ |/ /__  
/_//_/  /____//___/  /_/ |_|\___/
 
limb3/ru/packages/wact/how_to_create_new_filter.txt · Последние изменения: 2010/11/10 10:02 (внешнее изменение)