It's a template engine, based on MODX syntax, with precompilation in php code
Для установки выполните команду
composer require "amcms\quad"
Так как шаблонизатор не реализует некоторую логику получения полей, нужно создать новый класс, наследуемый от Amcms\Quad\Quad и в дальнейшем использовать его:
class Api extends Amcms\Quad\Quad {
public function getField($name, $binding = null, $binding_arg = null) {
// получение поля документа
}
public function getConfig($name) {
// получение системной настройки
}
public function getLang($name) {
// получение локализованных значений
}
public function makeUrl($id) {
// создание url из идентификатора документа
}
public function runSnippet($name, $params = [], $cached = true) {
$result = parent::runSnippet($name, $params, $cached);
if ($cached) {
// дополнительные действия по кешированию сниппета
}
return $result;
}
}
$api = new Api([
'cache' => __DIR__ . '/cache', // размещение скомпилированных шаблонов (или false)
]);
// первый добавленный источник шаблонов будет источником по умолчанию.
// источник для @FILE
$api->addSource(new \Amcms\Quad\Sources\FileSource($api, [
'templates' => __DIR__ . '/templates',
]));
// также, чтобы указать источник по умолчанию, можно указать второй параметр как true.
// источник для @CODE
$api->addSource(new \Amcms\Quad\Sources\CodeSource($api), true);
// источник для @CHUNK
$api->addSource(new \Amcms\Quad\Sources\ChunkSource($api, [
'templates' => __DIR__ . '/templates/chunks',
]));
После инициализации система должна зарегистрировать все используемые сниппеты и модификаторы:
$api->registerSnippet('snippet_name', function($params) {
// код сниппета
});
$api->registerFilter('filter_name', function($params) {
// код модификатора
})
[+placeholder+]
- Вывод плейсхолдера
[*field*]
- Вывод поля документа
[(setting)]
- Вывод системной опции
[%lang%]
- Вывод локализованного значения
{{chunk}}
- Вывод чанка
[[snippet]]
, [!snippet!]
- Выполнение сниппета и вывод результата
[-comment-]
- Комментарий
Плейсхолдеры могут быть установлены глобально с помощью метода Quad::setPlaceholder
, либо переданы массивом в функцию Quad::renderTemplate
в качестве второго параметра - тогда они будут видимы только в пределах соответствующего им шаблона/чанка.
При выводе сначала проверяется наличие локальных плейсхолдеров, затем глобальных.
Шаблонизатор не предусматривает логику работы с документами, поэтому система должна сама реализовывать метод Quad::getField
.
Также возможо указание биндинга выводимого поля, для вывода полей документа, который не является текущим.
Формат вызова в этом случае такой:
[*field@binding(binding_value)*]
Например:
[*pagetitle@parent*] - получение заголовка родительского документа;
[*pagetitle@26*] - получение заголовка документа под номером 26;
[*pagetitle@uparent(2)*] - получение заголовка родителя второго уровня;
Сама логика получения полей документов также должна быть реализована использующей системой.
Шаблонизатор не предусматривает логику получения системных настроек, поэтому система должна сама реализовывать метод Quad::getConfig
.
Система должна реализовывать получение локализованных значений через метод Quad::getLang
. Для склонения значений можно использовать модификатор key
.
Таким образом, источник значений и вывод могут выглядеть так:
...
$lang = [
1 => 'пользователь',
2 => 'пользователя',
...
];
...
[%user:key=`2`%] // выведет "пользователя"
По сути, чанки - это те же шаблоны, с некоторыми отличиями:
- обычно содержат небольшие по размеру участки кода, для многократного использования, либо для семантического разбиения;
- могут размещаться в отдельной папке;
Синтаксис вывода чанка из шаблона следующий:
{{chunk_name}} - простой вывод;
{{chunk_name? ¶m1=`value1` ¶m2=`value2`}} - вывод с параметрами
Аналогичные вызовы api-метода будут выглядеть так:
$api->parseChunk('chunk_name');
$api->parseChunk('chunk_name', ['param1' => 'value1', 'param2' => 'value2']);
Шаблонизатор реализует два способа вызова сниппета - кешированный и некешированный. Кеширование результата ложится на использующую систему.
Пример вызова:
[!snippet? ¶m1=`value1` ¶m2=`value2`!]
Тег [- ... -]
может быть использован для текстовых многострочных комментариев,
содержимое тега будет проигнорировано при компиляции.
Также, если нужно закомментировать вызов сниппета или чанка, достаточно перед именем сниппета/чанка
поставить знак -
. Например:
[!-snippet? ¶m1=`value1` ¶m2=`value2`!]
Чтобы передать шаблон в сниппет напрямую, а не сохраняя в чанк, можно использовать приставку @CODE
:
[[snippet? &tpl=`@CODE: [+a+]`]]
В inline-шаблонах не поддерживаются управляющие структуры и вложенные inline-шаблоны. В процессе компиляции inline-шаблоны проверяются наравне с другими элементами
Фильтры и модификаторы служат для быстрого изменения вывода путем применения к нему различных функций, например, частыми задачами являются экранирование, проверка на пустоту, форматирование и т.п.
Примеры применения фильтра:
[+value:escape+]
[+value:append=`test`+] - модификатор с параметром
[+value:append=`test`:escape+] - применение нескольких фильтров
[*pagetitle@uparent(2):escape*] - применение модификатора совместно с привязкой поля
[[snippet:escape? ¶m=`value`]] - применение модификатора к результату работы сниппета
Фильтры | ||
---|---|---|
Название | Параметр | Назначение |
contains | ||
containsnot | ||
empty | ||
!empty, notempty | ||
gt, isgt, greaterthan, isgreaterthan | ||
gte, isgte, ge, eg, equalorgreaterthan, greaterthanorequalto | ||
in, inarray, in_array | ||
is, eq, equals, equalto, isequal, isequalto | string | Возвращает результат сравнения значения с параметром |
lt, islt, lessthan, lowerthan, islessthan, islowerthan | ||
lte, islte, le, el, lessthanorequalto, equaltoorlessthan | ||
ne, neq, not, isnot, isnt, notequals, notequalto | ||
notin, !in, !inarray, notinarray, !in_array | ||
Модификаторы | ||
Название | Параметр | Назначение |
abs | ||
add, incr, increment, plus | ||
after, append | ||
capitalize, cap | ||
ceil | ||
dateformat, date_format, dateFormat, formatDate, format_date, date | ||
div, divide | ||
ellipsis | ||
e, esc, escape | ||
floor | ||
html_decode, decode_html, html_entity_decode | ||
htmlent, htmlentities | ||
htmlspecial, htmlspecchars, htmlspecialchars, hsc | ||
limit | ||
lcase, lowercase, strtolower, tolower, lower | ||
ltrim | ||
mod, modulus | ||
moneyformat, money_format | ||
mpe, multiply | ||
nl2br | ||
numberformat, number_format, numberFormat | ||
before, prepend | ||
replace | ||
reverse, strrev | ||
round | ||
rtrim | ||
spam_protect, spamprotect | ||
strip | ||
stripString, stripstring, stripstr, strip_string, strip_str | ||
striptags, stripTags, notags, strip_tags | ||
strtotime, totime | ||
subtract, decr, decrement, minus | ||
trim | ||
ucfirst | ||
ucwords | ||
ucase, uppercase, strtoupper, toupper, upper | ||
urldecode, url_decode, decode_url | ||
urlencode, url_encode, encode_url | ||
wordwrap | ||
wordwrapcut | ||
Геттеры | ||
Название | Параметр | Назначение |
default, ifempty, isempty | ||
else | ||
first | ||
ifnotempty, isnotempty | ||
key | ||
last | ||
length, len, strlen | ||
then |
Управляющие структуры недоступны в inline-шаблонах и внутренних вызовах.
{% for `item` in [[getItems]] %}
[+item+]
[+item_iteration+] - Номер итерации, начиная с 1
[+item_index+] - Номер итерации, начиная с 0
{% endfor %}
{% if [+value:is=`test`+] %}
value is test
{% elseif [+value:is=`test2`+] %}
value is test2
{% else %}
value is not test
{% endif %}
{% switch [+value+] %}
{% case `test` %}
value is test
{% endcase %}
{% default %}
value is not test
{% enddefault %}
{% endswitch %}