Reformat documentation

This commit is contained in:
bzick
2014-08-02 00:24:14 +04:00
parent 5972884c80
commit 0ff3ffc27f
60 changed files with 168 additions and 161 deletions

8
docs/en/adapters.md Normal file
View File

@ -0,0 +1,8 @@
Adapters
========
* [Fenom + Yii](https://bitbucket.org/RSol/rfenomviewrender)
* [Fenom + Kohana](https://github.com/2bj/kofenom) — Kofenom
* Fenom + Symphony
* Fenom + Symphony2
* Fenom + Zend Framework

6
docs/en/articles.md Normal file
View File

@ -0,0 +1,6 @@
Articles
========
## 2013
[Fenom — yet another PHP template engine](http://habrahabr.ru/post/169525/) [RU]

63
docs/en/benchmark.md Normal file
View File

@ -0,0 +1,63 @@
Benchmark
=========
To start benchmark use script `benchmark/run.php -h`.
### Smarty3 vs Twig vs Fenom
Smarty3 vs Twig vs Fenom
Generate templates... Done
Testing a lot output...
smarty3: !compiled and !loaded 3.9101 sec, 15.1 MiB
smarty3: compiled and !loaded 0.0235 sec, 9.3 MiB
smarty3: compiled and loaded 0.0015 sec, 9.3 MiB
twig: !compiled and !loaded 1.8725 sec, 68.9 MiB
twig: compiled and !loaded 0.0337 sec, 17.0 MiB
twig: compiled and loaded 0.0013 sec, 17.0 MiB
fenom: !compiled and !loaded 0.3157 sec, 8.9 MiB
fenom: compiled and !loaded 0.0159 sec, 6.6 MiB
fenom: compiled and loaded 0.0012 sec, 6.6 MiB
Testing 'foreach' of big array...
smarty3: !compiled and !loaded 0.0355 sec, 5.8 MiB
smarty3: compiled and !loaded 0.0032 sec, 3.1 MiB
smarty3: compiled and loaded 0.0024 sec, 3.1 MiB
twig: !compiled and !loaded 0.0799 sec, 4.7 MiB
twig: compiled and !loaded 0.0065 sec, 3.2 MiB
twig: compiled and loaded 0.0054 sec, 3.5 MiB
fenom: !compiled and !loaded 0.0459 sec, 3.1 MiB
fenom: compiled and !loaded 0.0024 sec, 2.5 MiB
fenom: compiled and loaded 0.0017 sec, 2.5 MiB
Testing deep 'inheritance'...
smarty3: !compiled and !loaded 0.3984 sec, 10.2 MiB
smarty3: compiled and !loaded 0.0009 sec, 3.1 MiB
smarty3: compiled and loaded 0.0001 sec, 3.1 MiB
twig: !compiled and !loaded 0.2897 sec, 11.2 MiB
twig: compiled and !loaded 0.0197 sec, 6.5 MiB
twig: compiled and loaded 0.0019 sec, 6.5 MiB
fenom: !compiled and !loaded 0.0546 sec, 3.2 MiB
fenom: compiled and !loaded 0.0005 sec, 2.5 MiB
fenom: compiled and loaded 0.0000 sec, 2.5 MiB
* **!compiled and !loaded** - template engine object created but parsers not initialized and templates not compiled
* **compiled and !loaded** - template engine object created, template compiled but not loaded
* **compiled and loaded** - template engine object created, template compiled and loaded
### Stats
| Template Engine | Files | Classes | Lines |
| --------------- | ------:| --------:| ------:|
| Smarty3 (3.1.13)| 320 | 190 | 55095 |
| Twig (1.13.0) | 162 | 131 | 13908 |
| Fenom (1.0.1) | 9 | 16 | 3899 |

3
docs/en/callbacks.md Normal file
View File

@ -0,0 +1,3 @@
Callbacks
=========

73
docs/en/configuration.md Normal file
View File

@ -0,0 +1,73 @@
Setup
=====
## Configure
### Template cache
```php
$fenom->setCompileDir($dir);
```
This method set the name of the directory where template caches are stored. By default this is `/tmp`. This directory must be writeable.
### Template settings
```php
// set options using factory
$fenom = Fenom::factory($tpl_dir, $compile_dir, $options);
// or inline using method setOptions
$fenom->setOptions($options);
```
Options may by associative array like `'option_name' => true` or bitwise mask.
| Option name | Constant | Description | Affect |
| ---------------------- | ------------------------- | ------------ | ------- |
| *disable_methods* | `Fenom::DENY_METHODS` | disable calling methods of objects in templates. | |
| *disable_native_funcs* | `Fenom::DENY_NATIVE_FUNCS`| disable calling native function in templates, except allowed. | |
| *auto_reload* | `Fenom::AUTO_RELOAD` | reload template if source will be changed | decreases performance |
| *force_compile* | `Fenom::FORCE_COMPILE` | recompile template every time when the template renders | very decreases performance |
| *disable_cache* | `Fenom::DISABLE_CACHE` | disable compile cache | greatly decreases performance |
| *force_include* | `Fenom::FORCE_INCLUDE` | paste template body instead of include-tag | increases performance, increases cache size |
| *auto_escape* | `Fenom::AUTO_ESCAPE` | html-escape each variables outputs | decreases performance |
| *force_verify* | `Fenom::FORCE_VERIFY` | check existence every used variable | decreases performance |
<!-- | *auto_trim* | `Fenom::AUTO_TRIM` | remove space-characters before and after tags | | -->
| *disable_statics* | `Fenom::DENY_STATICS` | disable calling static methods in templates. | |
| *strip* | `Fenom::AUTO_STRIP` | strip all whitespaces in templates. | decrease cache size |
```php
$fenom->setOptions(array(
"compile_check" => true,
"force_include" => true
));
// same
$fenom->setOptions(Fenom::AUTO_RELOAD | Fenom::FORCE_INCLUDE);
```
**Note**
By default all options disabled
## Extends
### Template providers
Бывает так что шаблны не хранятся на файловой сиситеме, а хранятся в некотором хранилище, например, в базе данных MySQL.
В этом случае шаблонизатору нужно описать как забирать шаблоны из хранилища, как проверять дату изменения шаблона и где хранить кеш шаблонов (опционально).
Эту задачу берут на себя Providers, это объекты реальзующие интерфейс `Fenom\ProviderInterface`.
### Callbacks and filters
#### Before compile callback
```php
$fenom->addPreFilter(function () { /* ... */ });
```
#### Tag filter callback
#### Filter callback
#### After compile callback

5
docs/en/dev/git.md Normal file
View File

@ -0,0 +1,5 @@
Git conversation
================
Ветка `master` содержит стабильную последнюю версию проекта. В ветку `master` может сливаться новая версия проекта из `develop` или исправления.
Ветка `develop`, для разработки, содержит не стабильную версию проекта. Принимает все новшевства, изменения и исправления.

88
docs/en/dev/internal.md Normal file
View File

@ -0,0 +1,88 @@
How it work
===========
## Терминология
* Исходный шаблон - изначальный вид шаблона в специальном синтаксисе
* Код шаблона - резальтат компиляции шаблона, PHP код.
* Провайдер - объект, источник исходных шаблонов.
## Классы
* `Fenom` - является хранилищем
* [шаблонов](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom.php#L88)
* [модификаторов](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom.php#L112)
* [фильтров](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom.php#L73)
* [тегов](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom.php#L140)
* [провайдеров](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom.php#L107)
* [настройки](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom.php#L98) - маска из [опций](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom.php#L29)
* [список](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom.php#L131) разрешенных функций
а также обладает соответсвующими setter-ами и getter-ами для настройки.
* `Fenom\Tokenizer` - разбирает, при помощи [tokens_get_all](http://docs.php.net/manual/en/function.token-get-all.php), строку на токены, которые хранит [массивом](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Tokenizer.php#L84).
Обладает методами для обработки токенов, работающими как с [конкретными токенами](http://docs.php.net/manual/en/tokens.php) так и с их [группами](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Tokenizer.php#L94).
* `Fenom\Render` - простейший шаблон. Хранит
* `Closure` с [PHP кодом](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Render.php#L30) шаблона
* [настройки](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Render.php#L19)
* [зависимости](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Render.php#L59)
* `Fenom\Template` - шаблон с функцией компиляции, расширен от `Fenom\Render`. Содержит различные методы для разбора выражений при помощи `Fenom\Tokenizer`.
* `Fenom\Compiler` - набор правил разбора различных тегов.
* `Fenom\Modifier` - набор модификаторов.
* `Fenom\Scope` - абстрактный уровень блочного тега.
* `Fenom\ProviderInterface` - интерфейс провадеров шаблонов
* `Fenom\Provider` - примитивный провайдер шаблонов с файловой системы.
## Процесс работы
При вызове метода `Fenom::display($template, $vars)` шаблонизатор [ищет](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom.php#L712) в своем хранилище уже загруженный шаблон.
Если шаблона [нет](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom.php#L727) - либо [загружает](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom.php#L762) код шаблона с файловой системыб либо [инициирует](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom.php#L759) его [компиляцию](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom.php#L788).
### Компиляция шаблонов
* [Создается](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom.php#L660) "пустой" `Fenom\Template`
* В него [загружется](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Template.php#L157) исходный шаблон [из провайдера](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Template.php#L167)
* Исходный шаблон проходит [pre-фильтры](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Template.php#L200).
* Начинается [разбор](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Template.php#L196) исходного шаблона.
* [Ищется](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Template.php#L204) первый открывающий тег символ - `{`
* [Смотрятся](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Template.php#L205) следующий за `{` символ.
* Если `}` или пробельный символ - ищется следующий символ `{`
* Если `*` - ищется `*}`, текст до которого, в последствии, вырезается.
* Ищется символ `}`. Полученный фрагмент шаблона считается тегом.
* Если [был тег](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Template.php#L238) `{ignore}` название тега проверяется на закрытие этого тега.
* Для тега [создается](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Template.php#L245) токенайзер и отдается в [диспетчер](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Template.php#L488) тегов
* Диспетчер тега вызывает различные парсеры выражений, компилятор тега и возвращает PHP код (см ниже).
* Полученный фрагмент PHP кода [обрабатывается и прикрепляется](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Template.php#L362) к коду шаблона.
* Ищется следующий `{` символ...
* ...
* В конце проверяется токенайзер на наличие не используемых токенов, если таковые есть - выбрасывается ошибка.
* [Проверяется](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Template.php#L264) стек на наличие не закрытых блоковых тегов
* PHP код проходит [post-фильтры](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Template.php#L282)
* Код шаблона [сохраняеться](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom.php#L799) на файлувую систему
* Код шаблона выполняется для использования
### Как работает токенайзер
Объек токенайзера принимает на вход любую строчку и разбирает ее при помощи функции token_get_all(). Полученные токен складываются в массив. Каждый токен прдсатвляет из себя числовой массив из 4-х элементов:
* Код токена. Это либо число либо один символ.
* Тело токена. Содержимое токена.
* Номер строки в исходной строке
* Пробельные символы, идущие за токеном
Токенайзер обладает внутренним указателем на "текущий" токен, передвигая указатель можно получить доступ к токенам через специальные функции-проверки. Почти все функции-проверки проверяют текущее значение на соответствие кода токену. Вместо кода может быть отдан код группы токенов.
### Как работает диспетчер тегов
* Проверяет, не является выражение в токенайзере [тегом ignore](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Template.php#L492).
* Проверяет, не является выражение в токенайзере [закрывающим тегом](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Template.php#L499).
* Проверяет, не является выражение в токенайзере [скалярным значением](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Template.php#L566).
* По имени тега из [списка тегов](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom.php#L140) выбирается массив и запускается [соответсвующий](https://github.com/bzick/fenom/blob/1.2.2/src/Fenom/Template.php#L582) парсер.
* Парсер возвращает PHP код
### Как работают парсеры
Парсер всегда получает объект токенайзера. Курсор токенайзера установлен на токен с которого начинается выражение, которое должен разобрать парсер.
Таким образом, по завершению разбора выражения, парсер должен установить курсор токенайзера на первый незнакомый ему символ.
Для примера рассмортим парсер переменной `Fenom\Template::parseVar()`.
В шаблоне имеется тег {$list.one.c|modifier:1.2}. В парсер будет отдан объект токенайзера `new Tokenizer('$list.one.c|modifier:1.2')` с токенами `$list` `.` `one` `.` `c` `|` `modifier` `:` `1.2`.
Указатель курсора установлен на токен `$list`. После разбора токенов, курсор будет установлен на `|` так как это не знакомый парсеру переменных токен. Следующий парсер может быть вызван `Fenom\Template::parseModifier()`, который распарсит модификатор.

12
docs/en/dev/readme.md Normal file
View File

@ -0,0 +1,12 @@
Develop
=======
If you want to discuss the enhancement of the Fenom, create an issue on Github or submit a pull request.
There tho branches — master and develop.
The branch master for stable releases and hotfixes; the branch develop for development of features. Each tag names by rule `major.minor.fix` (1.4.9, 1.1.2 etc) and creates from master. Version changes by the rule of [semantic versioning](http://semver.org/).
For questions: a.cobest@gmail.com (English, Russian languages)
* the [scheme of work](schema.md)

120
docs/en/dev/schema.md Normal file
View File

@ -0,0 +1,120 @@
How Fenom works
===============
```
use Fenom;
use Fenom\Render;
use Fenom\Template;
use Fenom\Tokenizer;
______________________________
| |
| Fenom::display($tpl, $var) |
|____________________________|
|
| search the template
______________|___________________________
| Template loaded into Fenom::$_storage? |
| Fenom::getTemplate($tpl) |
|________________________________________|
| |
| yes | no
______________|__________ |
| Render the template | |
| Render::display($tpl) | |
|_______________________| |
| |
| (hot start) |
| ______________________________|__________________
| | Template already compiled and stored in cache |
| | Fenom::getTemplate($template) |
| |_______________________________________________|
| | |
| | yes | no
| ____________|_______________ |
| | Load template from cache | not found |
| | Fenom::_load(...) |-------------->|
| |__________________________| |
| | |
| | found |
| ____________|___________ |
| | Validate template | invalid |
| | Render::isValid(...) |------------------>|
| |______________________| |
| | |
| | valid |
| ____________|____________ |
| | Render the template | |
|<----| Render::display(...) | |
| |_______________________| |
| |
| _____________________________ ________|___________________
| | Initialize compiler | | Compile the template |
| | Template::load($tpl) |<-----| Fenom::compile($tpl) |
| |___________________________| |__________________________|
| |
| ____________|________________
| | Load template source |
| | Provider::getSource($tpl) |
| |___________________________|
| |
| ____________|______________
| | Start compilation |
| | Template::compile($tpl) |
| |_________________________|
| |
| ____________|______________
| | Search template tag |
| | Template::compile($tpl) |<------------------------------------------------------|
| |_________________________| |
| | | |
| | not found | found |
| | _____________|_______________ _______________________________ |
| | | Tokenize the tag's code | | Parse the tag | |
| | | new Tokenizer($tag) |--->| Template::parseTag($tokens) | |
| | |___________________________| |_____________________________| |
| | | | |
| | is tag | | is expression |
| | _______________________________ | _______________|________________ |
| | | Detect tag name | | | Detect expression | |
| | | Template::parseAct($tokens) |<--- | Template::parseAct($tokens) | |
| | | Get callback by tag name | | Parse expression | |
| | | Fenom::getTag($tag_name) | | Template::parseExpr($tokens) | |
| | |_____________________________| |______________________________| |
| | | | |
| | | found | |
| | _______________|_______________ | |
| | | Invoke callback | | |
| | | Template::parseAct($tokens) | | |
| | |_____________________________| | |
| | | | |
| | _______________|________________ | |
| | | Append code to template | | |
| | | Template::_appendCode($code) |<----------------------- |
| | |______________________________| |
| | | |
| | _______________|___________ |
| | | Finalize the tag | starts search next tag |
| | | Template::compile($tpl) |>------------------------------------------------
| | |_________________________|
| |
| __|___________________________________
| | Store template to cache |
| | Fenom::compile($tpl) |
| | Store template to Fenom::$_storage |
| | Fenom::getTemplate($tpl) |
| |____________________________________|
| |
| ____________|_____________
| | Render the template |
| | Template::display(...) |
| |________________________|
| |
| | (cold start)
__|_________|________
| |
| DONE |
|___________________|
```

164
docs/en/ext/extend.md Normal file
View File

@ -0,0 +1,164 @@
Extends Fenom
=============
*TODO*
# Add tags
В шаблонизаторе принято различать два типа тегов: омпиляторы_ и ункции_.
Compilers invokes during compilation template to PHP source and have to
Компиляторы вызываются во время преобразования кода шаблона в PHP код и возвращяю PHP код который будет вставлен вместо тега.
А функции вызываются непременно в момент выполнения шаблона и возвращают непосредственно данные которые будут отображены.
Среди тегов как и в HTML есть строчные и блоковые теги.
## Inline function
Примитивное добавление функции можно осуществить следующим образом:
```php
$fenom->addFunction(string $function_name, callable $callback[, callable $parser]);
```
В данном случае запускается стандартный парсер, который автоматически разберет аргументы тега, которые должны быть в формате HTML аттрибутов и отдаст их в функцию ассоциативным массивом:
```php
$fenom->addFunction("some_function", function (array $params) { /* ... */ });
```
При необходимости можно переопределить парсер на произвольный:
```php
$fenom->addFunction("some_function", $some_function, function (Fenom\Tokenizer $tokenizer, Fenom\Template $template) { /* parse tag */});
```
Существует более простой способ добавления произвольной функции:
```php
$fenom->addFunctionSmarty(string $function_name, callable $callback);
```
В данном случае парсер сканирует список аргументов коллбека и попробует сопоставить с аргументами тега.
```php
// ... class XYCalcs ..
public static function calc($x, $y = 5) { /* ... */}
// ...
$fenom->addFunctionSmart('calc', 'XYCalcs::calc');
```
then
```smarty
{calc x=$top y=50} or {calc y=50 x=$top} is XYCalcs::calc($top, 50)
{calc x=$top} or {calc $top} is XYCalcs::calc($top)
```
Таким образом вы успешно можете добавлять Ваши функции или методы.
## Block function
Добавление блоковой функции аналогичен добавлению строковой за исключением того что есть возможность указать парсер для закрывающего тега.
```php
$fenom->addBlockFunction(string $function_name, callable $callback[, callable $parser_open[, callable $parser_close]]);
```
Сам коллбек принимает первым аргументом контент между открывающим и закрывающим тегом, а вторым аргументом - ассоциативный массив из аргуметов тега:
```php
$fenom->addBlockFunction('some_block_function', function ($content, array $params) { /* ... */});
```
## Inline compiler
Добавление строчного компилятора осуществляеться очень просто:
```php
$fenom->addCompiler(string $compiler, callable $parser);
```
Парсер должен принимать `Fenom\Tokenizer $tokenizer`, `Fenom\Template $template` и возвращать PHP код.
Компилятор так же можно импортировать из класса автоматически
```php
$fenom->addCompilerSmart(string $compiler, $storage);
```
`$storage` может быть как классом так и объектом. В данном случае шаблонизатор будет искать метод `tag{$compiler}`, который будет взят в качестве парсера тега.
## Block compiler
Добавление блочного компилятора осуществяется двумя способами. Первый
```php
$fenom->addBlockCompiler(string $compiler, array $parsers, array $tags);
```
где `$parser` ассоциативный массив `["open" => parser, "close" => parser]`, сождержащий парсер на открывающий и на закрывающий тег, а `$tags` содержит список внутренних тегов в формате `["tag_name"] => parser`, которые могут быть использованы только с этим компилятором.
Второй способ добавления парсера через импортирование из класса или объекта методов:
```php
$fenom->addBlockCompilerSmart(string $compiler, $storage, array $tags, array $floats);
```
# Add modifiers
```
$fenom->addModifier(string $modifier, callable $callback);
```
* `$modifier` - название модификатора, которое будет использоваться в шаблоне
* `$callback` - коллбек, который будет вызван для изменения данных
For example:
```smarty
{$variable|my_modifier:$param1:$param2}
```
```php
$fenom->addModifier('my_modifier', function ($variable, $param1, $param2) {
// ...
});
```
# Extends test operator
```php
$fenom->addTest($name, $code);
?>
```
# Add template provider
Бывает так что шаблны не хранятся на файловой сиситеме, а хранятся в некотором хранилище, например, в базе данных MySQL.
В этом случае шаблонизатору нужно описать как забирать шаблоны из хранилища, как проверять дату изменения шаблона и где хранить кеш шаблонов (опционально).
Эту задачу берут на себя Providers, это объекты реальзующие интерфейс `Fenom\ProviderInterface`.
# Extends accessor
# Extends cache
Изначально Fenom не расчитывался на то что кеш скомпиленых шаблонов может располагаться не на файловой системе.
Однако, в теории, есть возможность реализовать свое кеширование для скомпиленых шаблонов без переопределения шаблонизатора.
Речь идет о своем протоколе, отличным от `file://`, который [можно определить](http://php.net/manual/en/class.streamwrapper.php) в PHP.
Ваш протол должени иметь класс реализации протокола как указан в документации [Stream Wrapper](http://www.php.net/manual/en/class.streamwrapper.php).
Класс протокола может иметь не все указанные в документации методы. Вот список методов, необходимых шаблонизатору:
* [CacheStreamWrapper::stream_open](http://www.php.net/manual/en/streamwrapper.stream-open.php)
* [CacheStreamWrapper::stream_write](http://www.php.net/manual/en/streamwrapper.stream-write.php)
* [CacheStreamWrapper::stream_close](http://www.php.net/manual/en/streamwrapper.stream-close.php)
* [CacheStreamWrapper::rename](http://www.php.net/manual/en/streamwrapper.rename.php)
For `include`:
* [CacheStreamWrapper::stream_stat](http://www.php.net/manual/en/streamwrapper.stream-stat.php)
* [CacheStreamWrapper::stream_read](http://www.php.net/manual/en/streamwrapper.stream-read.php)
* [CacheStreamWrapper::stream_eof](http://www.php.net/manual/en/streamwrapper.stream-eof.php)
**Note**
(On 2014-05-13) Zend OpCacher doesn't support custom protocols except `file://` and `phar://`.
For example,
```php
$this->setCacheDir("redis://hash/compiled/");
```
* `$cache = fopen("redis://hash/compiled/XnsbfeDnrd.php", "w");`
* `fwrite($cache, "... <template content> ...");`
* `fclose($cache);`
* `rename("redis://hash/compiled/XnsbfeDnrd.php", "redis://hash/compiled/main.php");`

View File

@ -0,0 +1,9 @@
Extensions
==========
* [Extra pack](https://github.com/bzick/fenom-extra) of add-ons for Fenom template engine.
* Tools for static files (css, js).
* Global variables
* Allow more hooks for extending
* Add variable container
* You can only use the necessary add-ons

View File

@ -0,0 +1,33 @@
Inheritance algorithm
=====================
Variant #1. Sunny.
| level.2.tpl | b1 | add new block | `$tpl->block['b1'] = $content;`
| level.2.tpl | b1 | rewrite block | `$tpl->block['b1'] = $content;`
| level.1.tpl | b1 | skip because block exists | `if(!isset($tpl->block['b1'])) $tpl->block['b1'] = $content;`
| use.tpl | b1 | skip because block exists | `if(!isset($tpl->block['b1'])) $tpl->block['b1'] = $content;`
| use.tpl | b2 | add new block | `$tpl->block['b2'] = $content;`
| level.1.tpl | b2 | rewrite block | `$tpl->block['b2'] = $content;`
| parent.tpl | b1 | get block from stack
| parent.tpl | b2 | get block from stack
| parent.tpl | b3 | get own block
------Result--------
| level.2.tpl | b1 |
| level.1.tpl | b2 |
Variant #2. Сloudy.
| level.2.tpl | b1 | add new block
| level.1.tpl | b1 | skip because block exists
| use.tpl | b1 | skip because block exists
| use.tpl | b2 | add new block
| level.1.tpl | b2 | rewrite block
| $parent | b1 | dynamic extend
------Result--------
| level.2.tpl | b1 |
| level.1.tpl | b2 |
Variant #3. Rain.
Variant #4. Tornado.

22
docs/en/ext/mods.md Normal file
View File

@ -0,0 +1,22 @@
Модификаторы [RU]
============
```
$fenom->addModifier(string $modifier, callable $callback);
```
* `$modifier` - название модификатора, которое будет использоваться в шаблоне
* `$callback` - коллбек, который будет вызван для изменения данных
For example:
```smarty
{$variable|my_modifier:$param1:$param2}
```
```php
$fenom->addModifier('my_modifier', function ($variable, $param1, $param2) {
// ...
});
```

9
docs/en/ext/parsing.md Normal file
View File

@ -0,0 +1,9 @@
Parsing templates [RU]
======================
### Tokenizer
Объект Tokenizer содержит список готовых к обработке токенов и необходимые для фильтрации токенов методы. Помимо основнях констант расширения Tokenizer у объекта есть макросы, объединения, определенных токенов.
### Parsers

8
docs/en/ext/provider.md Normal file
View File

@ -0,0 +1,8 @@
Add template provider [RU]
=====================
Источники шаблонов позволяют хранить шаблоны не только на файловой системе, а там где вам удобдно будет. Что бы указать откуда нужно взять шаблон используется схема в имени шаблона `db:page/about.tpl`, шаблон будет взят из источника `db`. Источник шаблонов добавляется через метод `addProvider`, при добавлении необходимо указать схему по которой можно запросить шаблон из этого источника:
```php
$fenom->addProvider("db", $db_provider);
```

90
docs/en/ext/tags.md Normal file
View File

@ -0,0 +1,90 @@
Tags [RU]
=========
В шаблонизаторе принято различать два типа тегов: омпиляторы_ и ункции_.
Компиляторы вызываются во время преобразования кода шаблона в PHP код и возвращяю PHP код который будет вставлен вместо тега.
А функции вызываются непременно в момент выполнения шаблона и возвращают непосредственно данные которые будут отображены.
Среди тегов как и в HTML есть строчные и блоковые теги.
## Inline function
Примитивное добавление функции можно осуществить следующим образом:
```php
$fenom->addFunction(string $function_name, callable $callback[, callable $parser]);
```
В данном случае запускается стандартный парсер, который автоматически разберет аргументы тега, которые должны быть в формате HTML аттрибутов и отдаст их в функцию ассоциативным массивом:
```php
$fenom->addFunction("some_function", function (array $params) { /* ... */ });
```
При необходимости можно переопределить парсер на произвольный:
```php
$fenom->addFunction("some_function", $some_function, function (Fenom\Tokenizer $tokenizer, Fenom\Template $template) { /* parse tag */});
```
Существует более простой способ добавления произвольной функции:
```php
$fenom->addFunctionSmarty(string $function_name, callable $callback);
```
В данном случае парсер сканирует список аргументов коллбека и попробует сопоставить с аргументами тега.
```php
// ... class XYCalcs ..
public static function calc($x, $y = 5) { /* ... */}
// ...
$fenom->addFunctionSmart('calc', 'XYCalcs::calc');
```
then
```smarty
{calc x=$top y=50} or {calc y=50 x=$top} is XYCalcs::calc($top, 50)
{calc x=$top} or {calc $top} is XYCalcs::calc($top)
```
Таким образом вы успешно можете добавлять Ваши функции или методы.
## Block function
Добавление блоковой функции аналогичен добавлению строковой за исключением того что есть возможность указать парсер для закрывающего тега.
```php
$fenom->addBlockFunction(string $function_name, callable $callback[, callable $parser_open[, callable $parser_close]]);
```
Сам коллбек принимает первым аргументом контент между открывающим и закрывающим тегом, а вторым аргументом - ассоциативный массив из аргуметов тега:
```php
$fenom->addBlockFunction('some_block_function', function ($content, array $params) { /* ... */});
```
## Inline compiler
Добавление строчного компилятора осуществляеться очень просто:
```php
$fenom->addCompiler(string $compiler, callable $parser);
```
Парсер должен принимать `Fenom\Tokenizer $tokenizer`, `Fenom\Template $template` и возвращать PHP код.
Компилятор так же можно импортировать из класса автоматически
```php
$fenom->addCompilerSmart(string $compiler, $storage);
```
`$storage` может быть как классом так и объектом. В данном случае шаблонизатор будет искать метод `tag{$compiler}`, который будет взят в качестве парсера тега.
## Block compiler
Добавление блочного компилятора осуществяется двумя способами. Первый
```php
$fenom->addBlockCompiler(string $compiler, array $parsers, array $tags);
```
где `$parser` ассоциативный массив `["open" => parser, "close" => parser]`, сождержащий парсер на открывающий и на закрывающий тег, а `$tags` содержит список внутренних тегов в формате `["tag_name"] => parser`, которые могут быть использованы только с этим компилятором.
Второй способ добавления парсера через импортирование из класса или объекта методов:
```php
$fenom->addBlockCompilerSmart(string $compiler, $storage, array $tags, array $floats);
```

9
docs/en/helpme.md Normal file
View File

@ -0,0 +1,9 @@
Требуется помощь в переводе документации
========================================
Принимаю любую помощь в переводе статей документации. Вносить правки в документацию можете любым удобным способом:
* Сделать merge request (нажав `Edit` вверху файла)
* Прислать адрес статьи и что на что заменить. В письме лучше укажите `Fenom docs`.
Заранее благодарен!

View File

@ -0,0 +1,19 @@
Modifier date_format
====================
This formats a date and time into the given [strftime()](http://docs.php.net/strftime) format.
Dates can be passed to Fenom as unix timestamps, DateTime objects or any string made up of month day year, parsable by [strftime()](http://docs.php.net/strftime).
By default format is: `%b %e, %Y`.
```smarty
{var $ts = time()}
{$ts|date_format:"%Y/%m/%d %H:%M:%s"} outputs 2013/02/08 21:01:43
{$ts|date_format:"-1 day"} outputs 2013/02/07 21:01:43
{var $date = "2008-12-08"}
{$ts|date_format:"%Y/%m/%d %H:%M:%s"} outputs 2008/12/08 00:00:00
```
[Allowed quantificators](http://docs.php.net/strftime#refsect1-function.strftime-parameters) in **date_format**

18
docs/en/mods/ematch.md Normal file
View File

@ -0,0 +1,18 @@
Modifier ematch
==============
Perform a regular expression match.
[Read more](http://www.php.net/manual/en/reference.pcre.pattern.syntax.php) about regular expression.
```
{$string|ematch:$pattern}
```
Searches `$string` for a match to the regular expression given in `$pattern`.
```smarty
{if $color|ematch:'/^gr[ae]y$/i'}
some form of gray ...
{/if}
```

23
docs/en/mods/ereplace.md Normal file
View File

@ -0,0 +1,23 @@
Modifier ereplace
=================
Perform a regular expression search and replace.
[Read more](http://www.php.net/manual/en/reference.pcre.pattern.syntax.php) about regular expression.
```
{$string|replace:$pattern:$replacement}
```
Searches `$string` for matches to `$pattern` and replaces them with `$replacement`.
`$replacement` may contain references of the form `\n`, `$n` or `${n}`, with the latter form being the preferred one.
Every such reference will be replaced by the text captured by the n'th parenthesized pattern. n can be from 0 to 99,
and `\0` or `$0` refers to the text matched by the whole pattern.
Opening parentheses are counted from left to right (starting from 1) to obtain the number of the capturing subpattern.
To use backslash in replacement, it must be doubled.
```smarty
{var $string = 'April 15, 2014'}
{$string|ereplace:'/(\w+) (\d+), (\d+)/i':'${1}1, $3'} {* April1, 2014 *}
```

20
docs/en/mods/escape.md Normal file
View File

@ -0,0 +1,20 @@
Modifier escape
===============
The modifier escapes a string for safe insertion into the output.
It supports different escaping strategies depending on the template context.
By default, it uses the HTML escaping strategy:
```smarty
{$post.title|escape:'html'}
```
The modifier supports the following escaping strategies:
* html: escapes a string for the HTML body context.
* url: escapes a string for the URI or parameter contexts.
* js: escapes a string for the JavaScript context.
For convenience, the `e` modifier is defined as an alias of `escape` modifier.
Second parameter is charset.

19
docs/en/mods/esplit.md Normal file
View File

@ -0,0 +1,19 @@
Modifier esplit
===============
Split string by a regular expression.
[Read more](http://www.php.net/manual/en/reference.pcre.pattern.syntax.php) about regular expression.
```
{$string|esplit:$pattern = '/,\s*/'}
```
My default modifier split string by comma with spaces.
```smarty
{var $fruits1 = "banana, apple, pear"|esplit}
$fruits1 is array ["banana", "apple", "pear"]
{var $fruits2 = "banana; apple; pear"|esplit:'/;\s/'} is ["banana", "apple", "pear"]
$fruits2 is array ["banana", "apple", "pear"] too
```

10
docs/en/mods/in.md Normal file
View File

@ -0,0 +1,10 @@
Modifier in
===========
The modifier is implementation of [in](../operators.md#containment-operator) operator (performs containment test).
```smarty
{if $number|in:[1, 3, 42]}
...
{/if}
```

16
docs/en/mods/join.md Normal file
View File

@ -0,0 +1,16 @@
Modifier split
==============
Join array elements with a string.
```
{$string|join:$delimiter = ","}
```
Returns an array of strings, each of which is a substring of `$string` formed by splitting it on boundaries formed by the string `$delimiter`.
```smarty
{var $fruits1 = ["banana", "apple", "pear"]}
{$fruits1|join} output banana, apple, pear
{$fruits1|join:" is not "} output banana is not apple is not pear
```

10
docs/en/mods/length.md Normal file
View File

@ -0,0 +1,10 @@
Modifier length
===============
The modifier returns the number of items of a sequence or mapping, or the length of a string (works with UTF8 without `mbstring`)
```smarty
{if $images|length > 5}
to many images
{/if}
```

13
docs/en/mods/lower.md Normal file
View File

@ -0,0 +1,13 @@
Modifier lower
==============
Modifier is used to lowercase a variable or string. Have short alias `low`
This is equivalent to the PHP [strtolower()](http://docs.php.net/lower) function.
```smarty
{var $name = "Bzick"}
{$name} output Bzick
{$name|upper} output bzick
{$name|up} output bzick too
```

24
docs/en/mods/match.md Normal file
View File

@ -0,0 +1,24 @@
Modifier match
==============
Match string against a pattern.
The average user may be used to shell patterns or at least in their simplest form to `?` and `*` wildcards so using `match`
instead of `ematch` for frontend search expression input may be way more convenient for non-programming users.
```
{$string|match:$pattern}
```
Special pattern symbols:
* `?` — match one or zero unknown characters. `?at` matches `Cat`, `cat`, `Bat` or `bat` but not `at`.
* `*` — match any number of unknown characters. `Law*` matches `Law`, `Laws`, or `Lawyer`.
* `[characters]` — Match a character as part of a group of characters. `[CB]at` matches `Cat` or `Bat` but not `cat`, `rat` or `bat`.
* `\` - Escape character. `Law\*` will only match `Law*`
```smarty
{if $color|match:"*gr[ae]y"}
some form of gray ...
{/if}
```

14
docs/en/mods/replace.md Normal file
View File

@ -0,0 +1,14 @@
Modifier replace
================
Replace all occurrences of the search string with the replacement string
```
{$string|replace:$search:$replace}
```
This modifier returns a string with all occurrences of `$search` in subject replaced with the given `$replace` value.
```smarty
{$fruits|replace:"pear":"orange"}
```

18
docs/en/mods/split.md Normal file
View File

@ -0,0 +1,18 @@
Modifier split
==============
Split a string by string
```
{$string|split:$delimiter = ","}
```
Returns an array of strings, each of which is a substring of `$string` formed by splitting it on boundaries formed by the string `$delimiter`.
```smarty
{var $fruits1 = "banana,apple,pear"|split}
$fruits1 is array ["banana", "apple", "pear"]
{var $fruits2 = "banana,apple,pear"|split:',apple,'}
$fruits2 is array ["banana", "pear"]
```

16
docs/en/mods/strip.md Normal file
View File

@ -0,0 +1,16 @@
Modifier strip
==============
This replaces all repeated spaces and tabs with a single space, or with the supplied string.
```smarty
{" one two "|strip} => 'one two'
```
Optional boolean parameter tell to the modifier strip also newline
```smarty
{" multi
line
text "|strip:true} => 'multi line text'
```

22
docs/en/mods/truncate.md Normal file
View File

@ -0,0 +1,22 @@
Modifier truncate
=================
Modifier truncates a variable to a character length.
```smarty
{$long_string|truncate:$length:$etc:$by_words:$middle}
```
* `$length`, required. Parameter determines how many characters to truncate to.
* `$etc`, by default `...`. This is a text string that replaces the truncated text.
* `$by_word`, by default **FALSE**. This determines whether or not to truncate at a word boundary with TRUE, or at the exact character with FALSE.
* `$middle`, by default **FALSE**. This determines whether the truncation happens at the end of the string with FALSE, or in the middle of the string with TRUE.
```smarty
{var $str = "very very long string"}
{$str|truncate:10:" read more..."} output: very very read more...
{$str|truncate:5:" ... ":true:true} output: very ... string
```
Modifier do not use `mbstring` when works with UTF8.

5
docs/en/mods/unescape.md Normal file
View File

@ -0,0 +1,5 @@
Modifier unescape
=================
`Unescape` is used to decode entity, html, js and URI. See [escape](./escape.md)

13
docs/en/mods/upper.md Normal file
View File

@ -0,0 +1,13 @@
Modifier upper
==============
Modifier is used to uppercase a variable or string. Has short alias `up`.
This is equivalent to the PHP [strtoupper()](http://docs.php.net/strtoupper) function.
```smarty
{var $name = "Bzick"}
{$name} outputs Bzick
{$name|upper} outputs BZICK
{$name|up} outputs BZICK too
```

141
docs/en/operators.md Normal file
View File

@ -0,0 +1,141 @@
Operators
=========
### Arithmetic operators
* `$a + $b` - addition
* `$a - $b` - subtraction
* `$a * $b` - multiplication
* `$a / $b` - division
* `$a % $b` - modulus
```smarty
{$a + $b * $c/$d - $e*5 + 1e3}
```
### Logical operators
* `$a || $b` - or
* `$a && $b` - and
* `!$a` - not, unary operator
* `$a and $b` - and
* `$a or $b` - or
* `$a xor $b` - xor
```smarty
{if $b && $c} ... {/if}
```
### Comparison operators
* `$a < $b` - less than
* `$a > $b` - greater than
* `$a <= $b` - less than or equal to
* `$a >= $b` - greater than or equal to
* `$a == $b` - equal
* `$a === $b` - identical
* `$a !== $b` - not identical
* `$a != $b` - not equal
* `$a <> $b` - not equal
```smarty
{if $b >= 5} ... {/if}
```
### Bitwise operators
* `$a | $b` - or
* `$a & $b` - and
* `$a ^ $b` - xor
* `~$a` - not, unary operator
* `$a << $b` - shift left
* `$a >> $b` - shift right
```smarty
{if $a & 1} {var $b = 4 | $flags} {/if}
```
### Assignment Operators
* `$a = $b` - assignment
* `$a += $b` - assignment with addition
* `$a -= $b` - assignment with subtraction
* `$a *= $b` - assignment with multiplication
* `$a /= $b` - assignment with division
* `$a %= $b` - assignment with modulus
* `$a &= $b` - assignment with bitwise And
* `$a |= $b` - assignment with bitwise or
* `$a ^= $b` - assignment with bitwise xor
* `$a <<= $b` - assignment with left shift
* `$a >>= $b` - assignment with right shift
```smarty
{var $b |= $flags}
```
### Incrementing/Decrementing operators
* `++$a` - increment the variable and use it
* `$a++` - use the variable and increment it
* `--$a` - decrement the variable and use it
* `$a--` - use the variable and decrement it
### String operator
* `$a ~ $b` - return concatenation of variables `$a` and `$b`
### Ternary operators
* `$a ? $b : $c` - returns `$b` if `$a` is not empty, and `$c` otherwise
* `$a ! $b : $c` - returns `$b` if `$a` is set, and `$c` otherwise
* `$a ?: $c` - returns `$a` if `$a` is not empty, and `$c` otherwise
* `$a !: $c` - returns `$a` if `$a` is set, and `$c` otherwise
```smarty
{var $a = true}
{$a ? 5 : 10} {* outputs 5 *}
{var $a = false}
{$a ? 5 : 10} {* outputs 10 *}
```
### Check operators
* `$a?` - returns `TRUE` if `$a` is not empty
* `$a!` - returns `TRUE` if `$a` is set
```smarty
{if $a?} {* instead of {if !empty($a)} *}
{if $a!} {* instead of {if isset($a)} *}
{$a?:"some text"} {* instead of {if empty($a) ? "some text" : $a} *}
{$a!:"some text"} {* instead of {if isset($a) ? $a : "some text"} *}
```
### Test operator
Tests can be negated by using the `is not` operator.
* `$a is $b` - $a identical $b
* `$a is integer` - test variable type. Type may be int/integer, bool/boolean, float/double/decimal, array, object, scalar, string, callback/callable, number/numeric.
* `$a is iterable` - test variable for iteration.
* `$a is template` - variable `$a` contain existing template name.
* `$a is empty` - checks if a variable is empty.
* `$a is set` - checks if a variable is set.
* `$a is even` - variable `$a` is even.
* `$a is odd` - variable `$a` is odd.
* `$a is MyClass` or `$a is \MyClass` - variable `$a` instance of `MyClass` class
### Containment operator
Tests can be negated by using the `not in` operator.
* `$a in $b` - variable `$a` contains in `$b`, $b may be string, plain or assoc array.
* `$a in list $b` - variable `$a` contains in array `$b` as value
* `$a in keys $b` - array `$b` contain key `$a`
* `$a in string $b` - variable `$a` contains in string `$b` as substring
```smarty
{'df' in 'abcdefg'}
{5 in [1, 5, 25, 125]}
{99 in keys [1, 5, 25, 99 => 125]}
```

86
docs/en/readme.md Normal file
View File

@ -0,0 +1,86 @@
Documentation
=============
**Please, help translate documentation to english or fix typos. [Read more](./helpme.md).**
### Fenom
* [Quick start](./start.md)
* [Usage](./start.md#install-fenom)
* [Framework adapters](./adapters.md)
* [For developers](./dev/readme.md)
* [Configuration](./configuration.md)
* [Syntax](./syntax.md)
* [Operators](./operators.md)
***
### Tags
[Usage](./syntax.md#tags)
* [var](./tags/var.md) — define variable
* [if](./tags/if.md), `elseif` and `else` — conditional statement
* [foreach](./tags/foreach.md), `foreaelse`, `break` and `continue` — traversing items in an array or object
* [for](./tags/for.md), `forelse`, `break` and `continue` — loop statement
* [switch](./tags/switch.md), `case`, `default`
* [cycle](./tags/cycle.md) — cycles on an array of values
* [include](./tags/include.md), `insert` — includes and evaluates the specified template
* [extends](./tags/extends.md), `use`, `block` and `parent` — template inheritance
* [filter](./tags/filter.md) — apply modifier on a block of template data
* [ignore](./tags/ignore.md) — ignore Fenom syntax
* [macro](./tags/macro.md) and `import` — template functions
* [autoescape](./tags/autoescape.md) — escape template fragment
* [raw](./tags/raw.md) — unescape template fragment
* [unset](./tags/unset.md) — unset a given variables
* or [add](./ext/extend.md#add-tags) yours
***
### Modifiers
[Usage](./syntax.md#modifiers)
* [upper](./mods/upper.md) aka `up` — convert to uppercase a string
* [lower](./mods/lower.md) aka `low` — convert to lowercase a string
* [date_format](./mods/date_format.md) - format date, timestamp via strftime() function
* [date](./mods/date.md) - format date, timestamp via date() function
* [truncate](./mods/truncate.md) — truncate thee string to specified length
* [escape](./mods/escape.md) aka `e` — escape the string
* [unescape](./mods/unescape.md) — unescape the string
* [strip](./mods/strip.md) — remove extra whitespaces
* [length](./mods/length.md) — calculate length of string, array, object
* [in](./mods/in.md) — find value in string or array
* [match](./mods/match.md) — match string against a pattern.
* [ematch](./mods/ematch.md) — perform a regular expression match.
* [replace](./mods/replace.md) — replace all occurrences of the search string with the replacement string.
* [ereplace](./mods/ereplace.md) — perform a regular expression search and replace.
* [split](./mods/split.md) — split a string by string.
* [esplit](./mods/esplit.md) — split string by a regular expression.
* [join](./mods/join.md) — join array elements with a string.
* allowed functions: `json_encode`, `json_decode`, `count`, `is_string`, `is_array`, `is_numeric`, `is_int`, `is_object`,
`strtotime`, `gettype`, `is_double`, `ip2long`, `long2ip`, `strip_tags`, `nl2br`
* or [add](./ext/extend.md#add-modifiers) yours
***
### Operators
* [Arithmetic operators](./operators.md#arithmetic-operators) — `+`, `-`, `*`, `/`, `%`
* [Logical operators](./operators.md#logical-operators) — `||`, `&&`, `!$var`, `and`, `or`, `xor`
* [Comparison operators](./operators.md#comparison-operators) — `>`, `>=`, `<`, `<=`, `==`, `!=`, `!==`, `<>`
* [Bitwise operators](./operators.md#bitwise-operators) — `|`, `&`, `^`, `~$var`, `>>`, `<<`
* [Assignment operators](./operators.md#assignment-operators) — `=`, `+=`, `-=`, `*=`, `/=`, `%=`, `&=`, `|=`, `^=`, `>>=`, `<<=`
* [String concatenation operator](./operators.md#string-operator) — `$str1 ~ $str2`
* [Ternary operators](./operators.md#ternary-operators) — `$a ? $b : $c`, `$a ! $b : $c`, `$a ?: $c`, `$a !: $c`
* [Check operators](./operators.md#check-operators) — `$var?`, `$var!`
* [Test operator](./operators.md#test-operator) — `is`, `is not`
* [Containment operator](./operators.md#containment-operator) — `in`, `not in`
***
### Extends
* [Extend Fenom](./ext/extend.md)
* [Add-ons](./ext/extensions.md)

68
docs/en/start.md Normal file
View File

@ -0,0 +1,68 @@
Basic usage
===========
## Install Fenom
### Composer
Add package Fenom in your require-list in `composer.json`:
```json
{
"require": {
"fenom/fenom": "2.*"
}
}
```
and update project's dependencies: `composer update`.
### Custom loader
Clone Fenom to any directory: `git clone https://github.com/bzick/fenom.git`. Recommended use latest tag.
Fenom use [psr-0](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md#autoloading-standard) autoloading standard. Therefore you can
* use `psr-0` format in your project loader for loading Fenom's classes
* or register Fenom's autoloader: `Fenom::registerAutoload();` for loading itself.
Also you can use this autoloader for loading any library with `psr-0` file naming:
```php
Fenom::registerAutoload(PROJECT_DIR."/src");
```
## Setup Fenom
Create an object via factory method
```php
$fenom = Fenom::factory('/path/to/templates', '/path/to/compiled/template', $options);
```
Create an object via `new` operator
```php
$fenom = new Fenom(new Provider('/path/to/templates'));
$fenom->setCompileDir('/path/to/template/cache');
$fenom->setOptions($options);
```
* `/path/to/templates` — directory, where stores your templates.
* `/path/to/template/cache` — directory, where stores compiled templates in PHP files.
* `$options` - bit-mask or array of [Fenom settings](./configuration.md#template-settings).
### Use Fenom
Output template
```php
$fenom->display("template/name.tpl", $vars);
```
Get the result of rendering the template
```php
$result = $fenom->fetch("template/name.tpl", $vars);
```
Create the pipeline of rendering into callback
```php
$fenom->pipe(
"template/sitemap.tpl",
$vars,
$callback = [new SplFileObject("/tmp/sitemap.xml", "w"), "fwrite"], // pipe to file /tmp/sitemap.xml
$chunk_size = 1e6 // chunk size for callback
);
```

375
docs/en/syntax.md Normal file
View File

@ -0,0 +1,375 @@
Syntax
======
Fenom implements [Smarty](http://www.smarty.net/) syntax with some improvements.
All Fenom tags enclosed in the delimiters `{` and `}`, for example `{var $five = 5}`.
If you wanna leave delimiters as is in the template use [special statements or tags](#ignoring-delimiters).
**Note**
Fenom implements [Smarty](http://www.smarty.net/) syntax but not implements Smarty tags, however, some tags very similar.
But not so bad, Fenom has the [extras](https://github.com/bzick/fenom-extra) that make Fenom like Smarty.
## Variable
Variables in Fenom can be either displayed directly or used as arguments for functions, attributes and modifiers,
inside conditional expressions, etc.
### Use variables
Next example uses simple variables `$user_id` ans `$user_name`
```smarty
<div class="user">Hello, <a href="/users/{$user_id}">{$user_name}</a>.</div>
```
Example outputs next HTML code:
```html
<div class="user">Hello, <a href="/users/17">Bzick</a>.</div>
```
You can also reference associative array variables by specifying the key after a dot `.` symbol or paste key name into square brackets, as in PHP.
```smarty
<div class="user">Hello, <a href="/users/{$user.id}">{$user.name}</a>.</div>
```
`{$user.id}` and `{$user['id']}` are same:
```smarty
<div class="user">Hello, <a href="/users/{$user['id']}">{$user['name']}</a>.</div>
```
Properties of objects assigned from PHP can be referenced by specifying the property name after the `->` symbol:
```smarty
<div class="user">Hello, <a href="/users/{$user->id}">{$user->name}</a>.</div>
```
Methods of objects defined in PHP can be invoked by specifying the method name after the `->` symbol and use parenthesis with arguments:
```smarty
<div class="user">Hello, <a href="/users/{$user->getId()}">{$user->getName()}</a>.</div>
```
*Note*
Be careful, Fenom do not checks existence of the method before invoke.
To avoid the problem class of the object have to define method `__call`, which throws an exception, etc.
Also you can prohibit method call in [settings](./docs/configuration.md).
Below is complex example:
```smarty
{$foo.bar.baz}
{$foo.$bar.$baz}
{$foo[5].baz}
{$foo[5].$baz}
{$foo.bar.baz[4]}
{$foo[ $bar.baz ]}
{$foo[5]}
{$foo.5}
{$foo.bar}
{$foo.'bar'}
{$foo."bar"}
{$foo['bar']}
{$foo["bar"]}
{$foo.$bar}
{$foo[$bar]}
{$foo->bar}
{$foo->bar.buz}
{$foo->bar.buz[ $bar->getId("user") ]}
{$foo->bar(5)->buz(5.5)}
```
### System variable
Unnamed system variable starts with `$.` and allows access to global variables and template information:
* `$.get` is `$_GET`.
* `$.post` is `$_POST`.
* `$.cookie` is `$_COOKIE`.
* `$.session` is `$_SESSION`.
* `$.globals` is `$GLOBALS`.
* `$.request` is `$_REQUEST`.
* `$.files` is `$_FILES`.
* `$.server` is `$_SERVER`.
* `$.env` is `$_ENV`.
* `$.tpl.name` returns current template name.
* `$.tpl.schema` returns current schema of the template.
* `$.version` returns version of the Fenom.
* `$.const` paste constant.
```smarty
{if $.get.debug? && $.const.DEBUG}
...
{/if}
```
### Variable operations
Fenom supports math, logic, comparison, containment, test, concatenation operators...
todo
See all [operators](./operators.md)
### Set variable
```smarty
{var $foo = "bar"}
{var $foo = "bar"|upper} {* apply modifier *}
{var $foo = 5}
{var $foo = $x + $y}
{var $foo = $x.y[z] + $y}
{var $foo = strlen($a)} {* work with functions *}
{var $foo = myfunct( ($x+$y)*3 )}
{var $foo.bar.baz = 1} {* multidimensional value support *}
{var $foo = $object->item->method($y, 'named')} {* work with object fine *}
```
Using block tag
```smarty
{var $foo}
content {$text|truncate:30}
{/var}
{var $foo|truncate:50} {* apply modifier to content *}
content {$text}
{/var}
```
Set array
```smarty
{var $foo = [1, 2, 3]} numeric array
{var $foo = ['y' => 'yellow', 'b' => 'blue']} associative array
{var $foo = [1, [9, 8], 3]} can be nested
{var $foo = [1, $two, $three * 3 + 9]}
{var $foo = [$a, $d.c, $a + $f]}
{var $foo = ['y' => 'yellow', $color|upper => $colors[ $color ]}
{var $foo = [1, [$parent, $a->method()], 3]}
```
See also [{var}](./tags/var.md) documentation.
## Scalar values
### Strings
When the string in double quotation marks, all the expressions in the string will be run.
The result of expressions will be inserted into the string instead it.
```smarty
{var $foo="Username"}
{var $user.name="Username"}
{"Hi, $foo"} outputs "Hi, Username"
{"Hi, {$foo}"} outputs "Hi, Username"
{"Hi, {$user.name}"} outputs "Hi, Username"
{"Hi, {$user.name|up}"} outputs "Hi, USERNAME"
{"Hi, {$user->getName(true)}"} outputs Hi, Username
{var $message = "Hi, {$user.name}"}
```
but if use single quote any template expressions will be on display as it is
```smarty
{'Hi, $foo'} outputs 'Hi, $foo'
{'Hi, {$foo}'} outputs 'Hi, {$foo}'
{'Hi, {$user.name}'} outputs 'Hi, {$user.name}'
{'Hi, {$user.name|up}'} outputs "Hi, {$user.name|up}"
```
### Integers
Integers can be specified in decimal (base 10), hexadecimal (base 16), octal (base 8) or binary (base 2) notation, optionally preceded by a sign (- or +).
To use octal notation, precede the number with a 0 (zero). To use hexadecimal notation precede the number with 0x.
To use binary notation precede the number with 0b.
```smarty
{var $a = 1234} decimal number
{var $a = -123} a negative number
{var $a = 0123} octal number (equivalent to 83 decimal)
{var $a = 0x1A} hexadecimal number (equivalent to 26 decimal)
{var $a = 0b11111111} binary number (equivalent to 255 decimal)
```
**Note**
The size of an integer is platform-dependent, although a maximum value of about two billion is the usual value (that's 32 bits signed).
64-bit platforms usually have a maximum value of about 9223372036854775807
**Warning**
If an invalid digit is given in an octal integer (i.e. 8 or 9), the rest of the number is ignored.
### Floating point numbers
Floating point numbers (also known as "floats", "doubles", or "real numbers") can be specified using any of the following syntaxes:
```smarty
{var $a = 1.234}
{var $b = 1.2e3}
{var $c = 7E-10}
```
## Modifiers
Variable modifiers can be applied to variables, custom functions or strings.
To apply a modifier, specify the value followed by a | (pipe) and the modifier name.
A modifier may accept additional parameters that affect its behavior.
These parameters follow the modifier name and are separated by a : (colon).
```smarty
{var $foo="User"}
{$foo|upper} outputs "USER"
{$foo|lower} outputs "user"
{"{$foo|lower}"} outputs "user"
{"User"|lower}} outputs "user"
{$looong_text|truncate:80:"..."} truncate the text to 80 symbols and append <continue> symbols, like "..."
{$looong_text|lower|truncate:$settings.count:$settings.etc}
{var $foo="Ivan"|upper} sets $foo value "USER"
```
[List of modifiers](./main.md#modifiers)
## Tags
Basically, tag seems like
```smarty
{FUNCNAME attr1 = "val1" attr2 = $val2}
```
Tags starts with name and may have attributes
Это общий формат функций, но могут быть исключения, например функция [{var}](./tags/var.md), использованная выше.
```smarty
{include file="my.tpl"}
{var $foo=5}
{if $user.loggined}
Welcome, <span style="color: red">{$user.name}!</span>
{else}
Who are you?
{/if}
```
В общем случае аргументы принимают любой формат переменных, в том числе результаты арифметических операций и модификаторов.
```smarty
{funct arg=true}
{funct arg=5}
{funct arg=1.2}
{funct arg='string'}
{funct arg="string this {$var}"}
{funct arg=[1,2,34]}
{funct arg=$x}
{funct arg=$x.c}
```
```smarty
{funct arg="ivan"|upper}
{funct arg=$a.d.c|lower}
```
```smarty
{funct arg=1+2}
{funct arg=$a.d.c+4}
{funct arg=($a.d.c|count+4)/3}
```
## Static method support
By default static methods are allowed in templates
```smarty
{Lib\Math::multiple x=3 y=4} static method as tag
{Lib\Math::multiple(3,4)} inline static method
{12 + Lib\Math::multiple(3,4)}
{12 + 3|Lib\Math::multiple:4} static method as modifier
```
You may disable call static methods in template, see in [security options](./settings.md) option `deny_static`
## Ignoring template code
It is sometimes desirable or even necessary to have ignore sections it would otherwise parse.
A classic example is embedding Javascript or CSS code in a template.
The problem arises as those languages use the `{` and `}` characters which are also the default delimiters for Fenom.
Fenom has several solutions:
1. Uses block tag `{ignore} {/ignore}`. Anything within `{ignore} {/ignore}` tags is not interpreted, but displayed as-is.
2. The `{` and `}` braces will be ignored so long as they are surrounded by white space.
3. Uses tag option `:ignore` for block tag. Все Fenom теги внутри блока будут проигнорированны
Example:
```smarty
{ignore}
<style>
h1 {font-size: 24px; color: #F00;}
</style>
{/ignore}
<script>
(function (text) {
var e = document.createElement('P');
e.innerHTML = text;
document.body.appendChild(e);
})('test');
{if:ignore $cdn.yandex}
var item = {cdn: "//yandex.st/"};
{/if}
</script>
```
Outputs
```html
<style>
h1 {font-size: 24px; color: #F00;}
</style>
<script>
(function (text) {
var e = document.createElement('P');
e.innerHTML = text;
document.body.appendChild(e);
})('test');
var item = {cdn: "//yandex.st/"};
</script>
```
### Whitespaces
Tags to allow any number of spaces
```smarty
{include 'control.tpl'
$options = $list
$name = $cp.name
$type = 'select'
isolate = true
disable_static = true
}
{foreach [
"one" => 1,
"two" => 2,
"three" => 3
] as $key => $val}
{$key}: {$val}
{/foreach}
```
### Tag options
TODO
| name | code | type | description |
| ------- | ---- | ----- | ------------ |
| strip | s | block | enable `strip` option for a block of the template |
| raw | a | any | ignore escape option |
| escape | e | any | force escape |
| ignore | i | block | ignore Fenom syntax |
```smarty
{script:ignore} ... {/script}
{foreach:ignore:strip ...} ... {/foreach}
```

View File

@ -0,0 +1,14 @@
Tag {autoescape}
=====================
Force enable or disable `auto_escape` option for block area:
```smarty
{autoescape true}
...
Text: {$text} {* value of the variable $text will be escaped *}
...
{/autoescape}
```
Also see {raw} tag and :raw tag option

14
docs/en/tags/autotrim.md Normal file
View File

@ -0,0 +1,14 @@
Tag {autotrim}
==============
Force enable or disable `auto_trim` option for block area:
```smarty
{autotrim true}
...
Text: {$text} {* value of the variable $text will be escaped *}
...
{/autotrim}
```
Also see :trim, :rtrim and :ltrim tag options

13
docs/en/tags/cycle.md Normal file
View File

@ -0,0 +1,13 @@
Tag {cycle}
===========
```smarty
{for $i=$a.c..}
<div class="{cycle ["odd", "even"]}">
{/for}
{for $i=$a.c..}
<div class="{cycle ["odd", "even"] index=$i}">
{/for}
```

82
docs/en/tags/extends.md Normal file
View File

@ -0,0 +1,82 @@
Tag {extends} [RU]
==================
Тег `{extends}` реализует наследование шаблонов, иерархия, обратная {include}. То есть шаблон сам выбирает своего родителя.
### {extends}
Родительский шаблон можно задать единожды и до объявления какого-либо блока.
```smarty
{extends 'parent.tpl'}
```
Имя родительского шаблона может быть задан динамически, в этом случае производительность отрисовки может снизиться.
```smarty
{extends $parent_tpl}
```
### {block}
Блок указывает фрагмент шаблона, который будет передан родителю. Имя блока может быть задано как явно
```smarty
{block bk1}content 1{/block}
...
{block 'bk2'}content 2{/block}
```
так и не явно, но в данном случае пострадает производительность
```smarty
{block "bk{$number}"}content {$number}{/block}
...
{if $condition}
{block "bk-if"}content, then 'if' is true{/block}
{else}
{block "bk{$fail}"}content, then 'if' is false{/block}
{/if}
```
### {use}
Что бы импортировать блоки из другого шаблона используйте тег {use}:
```smarty
{use 'blocks.tpl'}
```
### {parent}
Planned. Not supported yet. Feature #5.
```smarty
{block 'block1'}
content ...
{parent}
content ...
{/block}
```
### Performance
Алгоритм реализации наследования шаблонов может работать в разных режимах, в зависимости от условий.
Каждый режим имеет свою производительность.
1. **Максимальная** производительность:
* Имена шаблонов в теге {extends } заданы явно, без использования переменных и условий.
* Имена блоков заданы явно, без использования переменных, условий и не вложены ни в какой другой тег.
2. **Средняя** производительность:
* Имена шаблонов в теге {extends } заданы явно, без использования переменных и условий.
* Имена блоков заданы **не** явно, с использованием переменныч, условий или могут быть вложенные в другие теги.
3. **Низкая** производительность:
* Имена шаблонов в теге {extends } заданы **не** явно, с использованием переменных и условий.
* Имена блоков заданы явно, без использования переменных, условий и не вложены ни в какой другой тег.
4. **Минимальная** производительность:
* Имена шаблонов в теге {extends } заданы **не** явно, с использованием переменных и условий.
* Имена блоков заданы **не** явно, с использованием переменных, условий или могут быть вложенные в другие теги.
Режим может идти только на понижение, при изменении условий во время прохождения по иерархии шаблонов.
При любом режиме работы не используется буферизация данных, то есть данные выводятся сразу.

10
docs/en/tags/filter.md Normal file
View File

@ -0,0 +1,10 @@
Tags {filter}
=============
Позволяет применить модификаторы на фрагмент шаблона
```smarty
{filter|strip_tags|truncate:20}
Remove all HTML <b>tags</b> and truncate {$text} to 20 symbols
{/filter}
```

40
docs/en/tags/for.md Normal file
View File

@ -0,0 +1,40 @@
Tag {for}
=========
```smarty
{for $counter=<start> to=<end> [step=<step>] [index=$index] [first=$first] [last=$last]}
{* ...code... *}
{break}
{* ...code... *}
{continue}
{* ...code... *}
{forelse}
{* ...code... *}
{/for}
```
### {for}
Переменная `$counter` принимает значение <start> и увеличивает своё значение на <step> на каждой итерации цикла пока не достигнет или не станет больше <end>.
<step> является необязательным аргументом. Если не указан, считается равным единице.
`$index` имеет значение номера текущей итерации. Первая итерация имеет номер 0.
`$first` равно **TRUE**, если итерация первая.
`$last` равно **TRUE**, если итерация последняя.
Поля `<start>`, `<end>`, `<step>` могут быть числами, или переменными, значение которых приводится к числовому.
Значением параметров _index_, _first_, _last_ может быть только переменная (допускаются вложенности на подобии `$a.b.c`, но массив `$a.b` должен быть объявлен).
### {break}
Тег `{break}` используется для выхода из цикла до достижения последней итерации. Если в цикле встречается тег {break}, цикл завершает свою работу, и далее выполняется код, следующий сразу за блоком цикла
### {continue}
Тег `{continue}` используется для прерывания текущей итерации. Если в цикле встречается тег {continue}, часть цикла, следующая после тега, не выполняется, и начинается следующая итерация. Если текущая итерация была последней, цикл завершается.
### {forelse}
Тег `{forelse}` ограничивает код, который должен быть выполнен, если сочетание полей <start>, <end> и <step> не обеспечивают ни одной итерации.

86
docs/en/tags/foreach.md Normal file
View File

@ -0,0 +1,86 @@
Tag {foreach} [RU]
==================
```smarty
{foreach $list as [$key =>] $value [index=$index] [first=$first] [last=$last]}
{* ...code... *}
{break}
{* ...code... *}
{continue}
{* ...code... *}
{foreachelse}
{* ...code... *}
{/foreach}
```
### {foreach}
Перебор значений массива $list
```smarty
{foreach $list as $value}
<div>{$value}</div>
{/foreach}
```
Перебор ключей и значений массива $list
```smarty
{foreach $list as $key => $value}
<div>{$key}: {$value}</div>
{/foreach}
```
Получение номера (индекса) итерации
```smarty
{foreach $list as $value index=$index}
<div>{$index}: {$value}</div>
{/foreach}
```
Определение первого элемента
```smarty
{foreach $list as $value first=$first}
<div>{if $first} first item {/if} {$value}</div>
{/foreach}
```
Переменная `$first` будет иметь значение **TRUE**, если текущая итерация является первой.
Определение последнего элемента
```smarty
{foreach $list as $value last=$last}
<div>{if $last} last item {/if} {$value}</div>
{/foreach}
```
Переменная `$last` будет иметь значение **TRUE**, если текущая итерация является последней.
### {break}
Тег `{break}` используется для выхода из цикла до достижения последней итерации. Если в цикле встречается тег `{break}`, цикл завершает свою работу, и далее, выполняется код, следующий сразу за блоком цикла
### {continue}
Тег `{continue}` используется для прерывания текущей итерации. Если в цикле встречается тег `{continue}`, часть цикла, следующая после тега, не выполняется, и начинается следующая итерация. Если текущая итерация была последней, цикл завершается.
### {foreachelse}
Тег {foreachelse} ограничивает код, который должен быть выполнен, если итерируемый объект пуст.
```smarty
{var $list = []}
{foreach $list as $value}
<div>{if $last} last item {/if} {$value}</div>
{foreachelse}
<div>empty</div>
{/foreach}
```
В блоке `{foreachelse}...{/foreach}` использование `{break}`, `{continue}` выбросит исключение `Fenom\CompileException` при компиляции
### Notice
Использование last требует от `$list` быть **countable**.

49
docs/en/tags/if.md Normal file
View File

@ -0,0 +1,49 @@
Tag {if} [RU]
=============
Реализация оператора [if](http://docs.php.net/if) из PHP
```smarty
{if <expression>}
{* ...code... *}
{elseif <expression>}
{* ...code... *}
{else}
{* ...code... *}
{/if}
```
### {if}
```smarty
{if <expression>}
{*...some code...*}
{/if}
```
Код, расположенный в теге `{if}` будет выполнен/выведен если выражение *<expression>* возвращает значение приводимое к **TRUE**
### {elseif}
```smarty
{if <expression1>}
{*...some code...*}
{elseif <expression2>}
{*...some code...*}
{/if}
```
Код, расположенный после тега `{elseif}` будет выполнен/выведен, если выражение <expression1> вернуло значение приводимое к **FALSE**, <expression2> - приводимое к **TRUE**
### {else}
```smarty
{if <expression>}
{*...some code...*}
{else}
{*...some code...*}
{/if}
```
Код, расположенный после тега `{else}` будет выполнен/выведен, если выражение <expression> вернуло значение приводимое к **FALSE**
В тестируемых выражениях могут быть использованы логические операторы , что позволяет обрабатывать сочетания нескольких условий.

19
docs/en/tags/ignore.md Normal file
View File

@ -0,0 +1,19 @@
Tag {ignore}
============
{ignore} tags allow a block of data to be taken literally.
This is typically used around Javascript or stylesheet blocks where {curly braces} would interfere with the template delimiter syntax.
Anything within {ignore}{/ignore} tags is not interpreted, but displayed as-is.
```smarty
{ignore}
var data = {"time": obj.ts};
{/ignore}
```
{ignore} tags are normally not necessary, as Fenom ignores delimiters that are surrounded by whitespace.
Be sure your javascript and CSS curly braces are surrounded by whitespace:
```smarty
var data = { "time": obj.ts };
```

46
docs/en/tags/include.md Normal file
View File

@ -0,0 +1,46 @@
Tag {include}
=============
`{include}` tags are used for including other templates in the current template. Any variables available in the current template are also available within the included template.
```smarty
{include "about.tpl"}
```
If you need to set yours variables for template list them in attributes.
```smarty
{include "about.tpl" page=$item limit=50}
```
All variables changed in child template has no affect to variables in parent template.
### {insert}
The tag insert template code instead self.
* No dynamic name allowed.
* No variables as attribute allowed.
* Increase performance because insert code as is in compilation time.
For example, main.tpl:
```smarty
a: {$a}
{insert 'b.tpl'}
c: {$c}
```
b.tpl:
```
b: {$b}
```
Code of `b.tpl` will be inserted into `main.tpl` as is:
```smarty
a: {$a}
b: {$b}
c: {$c}
```

54
docs/en/tags/macro.md Normal file
View File

@ -0,0 +1,54 @@
Tag {macro} [RU]
================
Макросы - фрагмент шаблона который можно повторить сколь угодно раз и в каком угодно месте.
Макросы не имеют общего пространства имен с шаблоном и могут оперировать только переданными переменными.
### {macro}
Обявление макроса происходит при помощи блочного тега `{macro}`
```smarty
{macro plus($x, $y, $z=0)}
x + y + z = {$x + $y + $z}
{/macro}
```
Вызов макроса происходит при помощи строкового тега `{macro}`. Аргументы передаются стандартно, как атрибуты в HTML тегах
```smarty
{macro.plus x=$num y=100}
```
Во время рекурсивного вызова используйте суффикс macro что бы обратиться к текущему макросу:
```smarty
{macro plus($x, $y, $z=0)}
...
{macro.plus x=2 y=$y}
...
{/macro}
```
### {import}
Для использования маросов в другом шаблоне необходимо их импортировать при помощи тега `{import}`
```smarty
{import 'math.tpl'}
```
При импорте можно указать дргое пространство имен что бы можно было использовать одноименные макросы из разных шаблонов
```smarty
{import 'math.tpl' as math}
...
{math.plus x=5 y=100}
```
Пространство имен макросов может совпадать с названием какого-либо тега, в данном случае ничего плохого не произойдет: будет вызван макрос, а тег не исчезнит
При необходимости можно импортировать только необходимые макросы, явно указав в теге `{import}`
```smarty
{import [plus, minus, exp] from 'math.tpl' as math}
```

30
docs/en/tags/raw.md Normal file
View File

@ -0,0 +1,30 @@
Tag {raw}
=========
Tag `{raw <expression>}` allow outputs render results without escaping.
This tag rewrite global option `auto_escape` for specified code.
```smarty
{autoescape true}
...
{$var|up} {* escape *}
{raw $var|up} {* unescape *}
...
{"name is: <b>{$name|low}</b>"} {* escape *}
{raw "name is: <b>{$name|low}</b>"} {* unescape *}
...
{/autoescate}
```
For functions use tag with prefix `raw:`:
```smarty
{autoescape true}
...
{my_func page=5} {* escape *}
{my_func:raw page=5} {* unescape *}
...
{/autoescate}
```
Tag can not be applied to compilers as `foreach`, `if` and other.

46
docs/en/tags/switch.md Normal file
View File

@ -0,0 +1,46 @@
Tag {switch}
============
The `{switch}` tag is similar to a series of `{if}` statements on the same expression.
In many occasions, you may want to compare the same variable (or expression) with many different values,
and execute a different piece of code depending on which value it equals to. This is exactly what the `{switch}` tag is for.
Tag `{switch}` accepts any expression. But `{case}` accepts only static scalar values or constants.
```smarty
{switch <condition>}
{case <value1>}
...
{case <value2>, <value3>, ...}
...
{case <value3>}
...
{case default, <value1>}
...
{/switch}
```
For example,
```smarty
{switch $type}
{case 'new'}
It is new item
{case 'current', 'new'}
It is new or current item
{case 'current'}
It is current item
{case 'new', 'newer'}
It is new item, again
{case default}
I don't know the type {$type}
{/switch}
```
if `$type = 'new'` then template output
```
It is new item
It is new or current item
It is new item, again
```

12
docs/en/tags/unset.md Normal file
View File

@ -0,0 +1,12 @@
Tag {unset}
===========
Unset a given variables.
```smarty
{unset $a} unset single variable
{unset $a $b $c.d.e} multiple unset
```

64
docs/en/tags/var.md Normal file
View File

@ -0,0 +1,64 @@
Tag {var}
=========
The tag {var} is used for assigning template variables during the execution of a template.
```smarty
{var $var=EXPR}
```
```smarty
{var $var}
... any content ...
{/var}
```
```smarty
{var $var|modifiers}
... any content ...
{/var}
```
Variable names follow the same rules as other labels in PHP.
A valid variable name starts with a letter or underscore, followed by any number of letters, numbers, or underscores.
```smarty
{var $v = 5}
{var $v = "value"}
{var $v = $x+$y}
{var $v = 4}
{var $v = $z++ + 1}
{var $v = --$z}
{var $v = $y/$x}
{var $v = $y-$x}
{var $v = $y*$x-2}
{var $v = ($y^$x)+7}
```
Creating array
```smarty
{var $v = [1,2,3]}
{var $v = []}
{var $v = ["one"|upper => 1, 4 => $x, "three" => 3]}
{var $v = ["key1" => $y*$x-2, "key2" => ["z" => $z]]}
```
Getting function result into variable
```smarty
{var $v = count([1,2,3])+7}
```
Collect the output of the template into a variable
```smarty
{var $v}
Some long {$text|trim}
{/var}
{var $v|escape} {* apply modifier to variable*}
Some long {$text|trim}
{/var}
```