This commit is contained in:
Ivan Shalganov 2014-08-08 12:04:52 +00:00
commit dc27199e8b
54 changed files with 908 additions and 710 deletions

View File

@ -13,4 +13,4 @@ script:
- phpunit
after_script:
- CODECLIMATE_REPO_TOKEN=6739bff0f9a6eb7eaa5cfd1b086b55a3413aff24991d793b5b12da91c3803471 ./vendor/bin/test-reporter
- php vendor/bin/coveralls

View File

@ -7,9 +7,9 @@ Fenom - Template Engine for PHP
[![Latest Stable Version](https://poser.pugx.org/fenom/fenom/v/stable.png)](https://packagist.org/packages/fenom/fenom)
[![Build Status](https://travis-ci.org/bzick/fenom.svg?branch=master)](https://travis-ci.org/bzick/fenom)
[![Coverage Status](https://coveralls.io/repos/bzick/fenom/badge.png?branch=master)](https://coveralls.io/r/bzick/fenom?branch=master)
[![Code Climate](https://codeclimate.com/github/bzick/fenom.png)](https://codeclimate.com/github/bzick/fenom)
[![Total Downloads](https://poser.pugx.org/fenom/fenom/downloads.png)](https://packagist.org/packages/fenom/fenom)
## [Quick start](./docs/en/start.md) :: [Documentation](./docs/readme.md) [en](./docs/en/readme.md)/[ru](./docs/ru/readme.md) :: [Benchmark](./docs/en/benchmark.md)
## [Quick start](./docs/en/start.md) :: [Documentation](./docs/readme.md) [[en](./docs/en/readme.md)|[ru](./docs/ru/readme.md)] :: [Benchmark](./docs/en/benchmark.md)
<!-- :: [Articles](./docs/articles.md) -->
### What is it

View File

@ -16,7 +16,7 @@
},
"require-dev": {
"phpunit/phpunit": "*",
"codeclimate/php-test-reporter": "dev-master"
"satooshi/php-coveralls": "dev-master"
},
"autoload": {
"psr-0": { "Fenom\\": "src/" },

View File

@ -1,5 +1,5 @@
Articles
========
Статьи
======
## 2013

View File

@ -50,27 +50,3 @@ $fenom->setOptions(Fenom::AUTO_RELOAD | Fenom::FORCE_INCLUDE);
**Замечание**
По умолчанию все параметры деактивированы.
## 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

90
docs/ru/dev/internal.md Normal file
View File

@ -0,0 +1,90 @@
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()`, который распарсит модификатор.

22
docs/ru/dev/readme.md Normal file
View File

@ -0,0 +1,22 @@
Develop
=======
Если у Вас есть что обсудить или предложить создайте issue на Github или сделайте запрос на сливание.
По вопросам можете слать письмо на email : a.cobest@gmail.com (Русский и английские языки)
## Соглашение по наименованию версий
Версии именуются согласо [Semantic Versioning 2.0.0](http://semver.org/).
## Соглашение по GIT
Ветка `master` содержит стабильную последнюю версию проекта.
В ветку `master` может сливаться новая версия проекта из `develop` или исправления.
Ветка `develop`, для разработки, содержит не стабильную версию проекта. Принимает новшевства, изменения и исправления.
## Принцип работы
Разобраться в принципе работы поможе [эта схема](schema.md).

120
docs/ru/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 |
|___________________|
```

View File

@ -1,9 +1,9 @@
Extends Fenom
=============
Расширение Fenom
================
*TODO*
# Add tags
# Добавление тегов
В шаблонизаторе принято различать два типа тегов: омпиляторы_ и ункции_.
Compilers invokes during compilation template to PHP source and have to
@ -11,7 +11,7 @@ Compilers invokes during compilation template to PHP source and have to
А функции вызываются непременно в момент выполнения шаблона и возвращают непосредственно данные которые будут отображены.
Среди тегов как и в HTML есть строчные и блоковые теги.
## Inline function
## Линейные функции
Примитивное добавление функции можно осуществить следующим образом:
@ -48,7 +48,7 @@ then
```
Таким образом вы успешно можете добавлять Ваши функции или методы.
## Block function
## Блоковые функции
Добавление блоковой функции аналогичен добавлению строковой за исключением того что есть возможность указать парсер для закрывающего тега.
@ -61,7 +61,7 @@ $fenom->addBlockFunction(string $function_name, callable $callback[, callable $p
$fenom->addBlockFunction('some_block_function', function ($content, array $params) { /* ... */});
```
## Inline compiler
## Линейный компилятор
Добавление строчного компилятора осуществляеться очень просто:
@ -78,7 +78,7 @@ $fenom->addCompilerSmart(string $compiler, $storage);
`$storage` может быть как классом так и объектом. В данном случае шаблонизатор будет искать метод `tag{$compiler}`, который будет взят в качестве парсера тега.
## Block compiler
## Блоковый компилятор
Добавление блочного компилятора осуществяется двумя способами. Первый
@ -93,7 +93,7 @@ $fenom->addBlockCompiler(string $compiler, array $parsers, array $tags);
$fenom->addBlockCompilerSmart(string $compiler, $storage, array $tags, array $floats);
```
# Add modifiers
# Добавление модификаторов
```
$fenom->addModifier(string $modifier, callable $callback);
@ -114,22 +114,55 @@ $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
Шаблоны можно получать из самых разных источников.
Когда вы отображаете или вызываете шаблон, либо когда вы подключаете один шаблон к другому, вы указываете источник,
вместе с соответствующим путём и названием шаблона. Если источник явно не задан, то используется источник `Fenom\Provider`,
который считывает шаблоны из указанной директории.
# Extends cache
Источник шаблонов должен реализовать интерфейс `Fenom\ProviderInterface`.
Используйте метод `$fenom->setProvider(...)` что бы добавить источник в шаблонизатор, указав навание источника и, если есть необходимость,
задать директорию кеша для шаблонов из этого источника. Рассмотрим на примере, реализуем источик шаблонов из базы данных.
Создадим источник:
```php
class DbProvider implements Fenom\ProviderInterface {
// ...
}
```
Добавляем источник, указав удобное имя.
```php
$provider = new DbProvider();
$fenom->setProvider("db", $provider, "/tmp/cached/db");
```
Теперь источник можно использовать.
```php
$fenom->display("db:index.tpl", $vars);
```
```smarty
{include "db:menu.tpl"}
```
# Расширение кеша (эксперементальное)
Изначально Fenom не расчитывался на то что кеш скомпиленых шаблонов может располагаться не на файловой системе.
Однако, в теории, есть возможность реализовать свое кеширование для скомпиленых шаблонов без переопределения шаблонизатора.
@ -150,9 +183,9 @@ For `include`:
* [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://`.
(On 2014-05-13) Zend OpCacher кроме `file://` и `phar://` не поддеривает другие протоколы.
For example,
Пример работы кеша
```php
$this->setCacheDir("redis://hash/compiled/");

View File

@ -1,33 +0,0 @@
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.

View File

@ -1,22 +0,0 @@
Модификаторы [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) {
// ...
});
```

View File

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

View File

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

4
docs/ru/inheritance.md Normal file
View File

@ -0,0 +1,4 @@
Наследование шаблонов
=====================
Документации пока нет, почитайте на хабре пока

View File

@ -1,19 +1,63 @@
Modifier date_format
Модификатор 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`.
Форматирует дату согласно указанному формату [strftime()](http://docs.php.net/ru/strftime).
Даты могут быть переданы в виде временных меток unix, временных меток mysql или в виде любой строки, содержащей день,
месяц и год, которую может обработать функция [strftime()](http://docs.php.net/ru/strftime).
```smarty
{$date|date_format:$format = `%b %e, %Y`}
```
Формат по умолчанию: `%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
{$ts|date_format:"%Y/%m/%d %H:%M:%s"} выведет 2013/02/08 21:01:43
{$ts|date_format:"-1 day"} выведет вчерашний день, например 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
{$ts|date_format:"%Y/%m/%d %H:%M:%s"} выведет 2008/12/08 00:00:00
```
[Allowed quantificators](http://docs.php.net/strftime#refsect1-function.strftime-parameters) in **date_format**
[Конверсионные указатели](http://docs.php.net/ru/strftime#refsect1-function.strftime-parameters) в модификаторе **date_format**:
* %a - сокращенное название дня недели, в зависимости от текущей локали
* %A - полное название дня недели, в зависимости от текущей локали
* %b - сокращенное название месяца, в зависимости от текущей локали
* %B - полное название месяца, в зависимости от текущей локали
* %c - формат даты и времени по умолчанию для текущей локали
* %C - номер века (год, деленный на 100, представленный в виде целого в промежутке от 00 до 99)
* %d - день месяца в десятичном формате (от 01 до 31)
* %D - синоним %m/%d/%y
* %e - день месяца в десятичном формате без ведущего нуля (от 1 до 31)
* %g - Week-based year within century [00,99]
* %G - Week-based year, including the century [0000,9999]
* %h - синоним %b
* %H - часы по 24-часовым часам (от 00 до 23)
* %I - часы по 12-часовым часам (от 01 до 12)
* %j - день года (от 001 до 366)
* %k - часы по 24-часовым часам без ведущего нуля (от 0 до 23)
* %l - часы по 12-часовым часам без ведущего нуля (от 1 до 12)
* %m - номер месяца (от 01 до 12)
* %M - минуты
* %n - символ новой строки
* %p - `am' или `pm', в зависимости от заданного формата времени и текущей локали.
* %r - time in a.m. and p.m. notation
* %R - time in 24 hour notation
* %S - секунды
* %t - символ табуляции
* %T - время в формате %H:%M:%S
* %u - номер дня недели [1,7], где 1-ый день - понедельник
* %U - номер недели в году, считая первое воскресенья года первым днем первой недели
* %V - номер недели в году (по ISO 8601:1988) в диапазоне от 01 до 53, где первая неделя та, у которой хотя бы 4 дня находятся в данном году. Понедельник считается первым днем недели.
* %w - номер дня недели, где 0 - воскресенье
* %W - номер недели в году, считаю первый понедельник первым днем первой недели.
* %x - предпочтительное представление даты для текущих настроек locale без времени
* %X - предпочтительное представление времени для текущих настроек locale без даты
* %y - год в виде десятичного числа без века (от 00 до 99)
* %Y - год в виде десятичного числа включая век
* %Z - часовой пояс или имя или сокращение
* %% - буквальный символ `%'

View File

@ -1,18 +1,18 @@
Modifier ematch
Модификатор ematch
==============
Perform a regular expression match.
[Read more](http://www.php.net/manual/en/reference.pcre.pattern.syntax.php) about regular expression.
Выполняет проверку на соответствие регулярному выражению.
[Подробнее](http://www.php.net/manual/ru/reference.pcre.pattern.syntax.php) о регулярных выражениях.
```
{$string|ematch:$pattern}
```
Searches `$string` for a match to the regular expression given in `$pattern`.
Ищет в заданном тексте `$subject` совпадения с шаблоном `$pattern`.
```smarty
{if $color|ematch:'/^gr[ae]y$/i'}
some form of gray ...
{if $color|ematch:'/^(.*?)gr[ae]y$/i'}
какой-то оттенок серого ...
{/if}
```

View File

@ -1,23 +1,25 @@
Modifier ereplace
Модификатор ereplace
=================
Perform a regular expression search and replace.
[Read more](http://www.php.net/manual/en/reference.pcre.pattern.syntax.php) about regular expression.
Выполняет поиск и замену по регулярному выражению.
[Подробнее](http://www.php.net/manual/ru/reference.pcre.pattern.syntax.php) о регулярных выражениях.
```
{$string|replace:$pattern:$replacement}
```
Searches `$string` for matches to `$pattern` and replaces them with `$replacement`.
Выполняет поиск совпадений в строке `$subject` с шаблоном pattern и заменяет их на replacement.
`$replacement` может содержать ссылки вида `\n`, `$n` или `${n}`, причем последний вариант предпочтительней.
Каждая такая ссылка будет заменена на подстроку, соответствующую n-ой подмаске. n может принимать значения от 0 до 99,
причем ссылка `\0` (либо $0) соответствует вхождению всего шаблона.
Подмаски нумеруются слева направо, начиная с единицы. Для использования обратного слэша, его необходимо продублировать.
`$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 *}
```
```
**Замечание:** воизбежание скрытых ошибок при выполнении сущностей регулярные выражения стоит помещать в одинарные кавычки.

View File

@ -1,20 +1,19 @@
Modifier escape
Модификатор 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:
Используется для кодирования или экранирования спецсимволов по алгоритмам экранирования HTML, URL'ов и javascript.
По умолчанию активирован режим экранирования HTML.
```smarty
{$post.title|escape:'html'}
{$text|escape:$type = 'html':$charset = 'UTF8'}
```
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.
* `html`: экранирует HTML сущности в строке.
* `url`: экранирует строку для использования в URL.
* `js`: экранирует строку для использования в JavaScript.
For convenience, the `e` modifier is defined as an alias of `escape` modifier.
Модификатор `e` является псевданимом модификатора от `escape`.
Second parameter is charset.
Параметр `$charset` указывает кодировку для режима `html`.

View File

@ -1,19 +1,19 @@
Modifier esplit
Модификатор esplit
===============
Split string by a regular expression.
[Read more](http://www.php.net/manual/en/reference.pcre.pattern.syntax.php) about regular expression.
Разбивает строку по регулярному выражению.
[Подробнее](http://www.php.net/manual/ru/reference.pcre.pattern.syntax.php) о регулярных выражениях.
```
{$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"]
$fruits1 — массив ["banana", "apple", "pear"]
{var $fruits2 = "banana; apple; pear"|esplit:'/;\s/'} is ["banana", "apple", "pear"]
$fruits2 is array ["banana", "apple", "pear"] too
$fruits2 — массив ["banana", "apple", "pear"]
```

View File

@ -1,7 +1,7 @@
Modifier in
Модификатор in
===========
The modifier is implementation of [in](../operators.md#containment-operator) operator (performs containment test).
Модификатор является реализацией оператора сдержания [in](../operators.md#Оператор-содержания).
```smarty
{if $number|in:[1, 3, 42]}

View File

@ -1,16 +1,16 @@
Modifier split
Модификатор split
==============
Join array elements with a string.
Объединяет элементы массива в строку.
```
{$string|join:$delimiter = ","}
{$array|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`.
Объединяет элементы массива с помощью строки `$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
{$fruits1|join} выведет banana, apple, pear
{$fruits1|join:" is not "} выведет banana is not apple is not pear
```

View File

@ -1,7 +1,7 @@
Modifier length
Модификатор length
===============
The modifier returns the number of items of a sequence or mapping, or the length of a string (works with UTF8 without `mbstring`)
Модификатор возвращает количество элементов массива, итератора или символов в строке (работает с UTF8).
```smarty
{if $images|length > 5}

View File

@ -1,13 +1,13 @@
Modifier lower
Модификатор 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.
Переводит строку в нижний регистр. Является эквивалентом функции PHP [strtolower()](http://docs.php.net/ru/lower).
Имеет псевданим `low`.
```smarty
{var $name = "Bzick"}
{set $name = "Bzick"}
{$name} output Bzick
{$name|upper} output bzick
{$name|up} output bzick too
{$name} выведет Bzick
{$name|upper} выведет bzick
{$name|up} выведет bzick
```

View File

@ -1,24 +1,26 @@
Modifier match
==============
Модификатор match
=================
Проверяет совпадение строки с паттерном.
Среднестатистический пользователь знаком с подстановками оболочки, как минимум с самыми простыми из них - `?` и `*`,
так что использование `match` вместо `ematch` для поиска в пользовательской части сайта может быть намного удобнее для пользователей,
не являющихся программистами.
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*`
* `?`соответствие одному или нулю любых символов. `?at` соответствует `Cat`, `cat`, `Bat` или `bat`.
* `*`соответствие любому количеству символов. `Law*` соответствует `Law`, `Laws`, или `Lawyer`.
* `[characters]`соответствие символа группе символов. `[CB]at` соответствует `Cat` или `Bat`, но не `cat`, `rat` или `bat`.
* `\` - экрнирующийсимвол. `Law\*` будет соответвовать только `Law*`
```smarty
{if $color|match:"*gr[ae]y"}
some form of gray ...
какой-то оттенок серого
{/if}
```

View File

@ -1,13 +1,13 @@
Modifier replace
Модификатор 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.
Этот модификатор возвращает строку, в котором все вхождения `$search` в `$subject` заменены на `$replace`.
```smarty
{$fruits|replace:"pear":"orange"}

View File

@ -1,13 +1,13 @@
Modifier split
Модификатор 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`.
Возвращает массив строк, полученных разбиением строки с использованием `$delimiter` в качестве разделителя.
```smarty
{var $fruits1 = "banana,apple,pear"|split}

View File

@ -1,16 +1,27 @@
Modifier strip
Модификатор strip
==============
Заменяет все повторяющиеся пробелы, переводы строк и символы табуляции одним пробелом.
This replaces all repeated spaces and tabs with a single space, or with the supplied string.
```smarty
{" one two "|strip} => 'one two'
{" one two "|strip}
```
Результат обработки
```
one two
```
Optional boolean parameter tell to the modifier strip also newline
Опционально указывается флаг мультистрочности: `true` - тку же срезать переносы строк, `false` - срезать все кроме переносов строк.
```smarty
{" multi
line
text "|strip:true} => 'multi line text'
text "|strip:true}
```
Результат обработки
```
multi line text
```

View File

@ -1,16 +1,17 @@
Modifier truncate
Модификатор truncate
=================
Modifier truncates a variable to a character length.
Обрезает переменную до определенной длинны, по умолчанию - 80 символов.
В качестве необязательного второго параметра, вы можете передать строку текста, которая будет отображатся в конце обрезанной переменной. Символы этой строки не включаются в общую длинну обрезаемой строки. По умолчанию, truncate попытается обрезать строку в промежутке между словами. Если вы хотите обрезать строку строго на указаной длинне, передайте в третий необязательный параметр значение true.
```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.
* `$length`, обязателен. Определяет максимальную длинну обрезаемой строки.
* `$etc`, по умолчанию `...`. Текстовая строка, которая заменяет обрезанный текст. Её длинна НЕ включена в максимальную длинну обрезаемой строки.
* `$by_word`, по умолчанию **FALSE**. Определяет, обрезать ли строку в промежутке между словами (true) или строго на указаной длинне (false).
* `$middle`, по умолчанию **FALSE**. Определяет, нужно ли обрезать строку в конце (false) или в середине строки (true).
```smarty
{var $str = "very very long string"}
@ -19,4 +20,4 @@ Modifier truncates a variable to a character length.
{$str|truncate:5:" ... ":true:true} output: very ... string
```
Modifier do not use `mbstring` when works with UTF8.
Модификатор работает с unicode без дополнительных расширений.

View File

@ -1,5 +1,9 @@
Modifier unescape
Модификатор unescape
=================
`Unescape` is used to decode entity, html, js and URI. See [escape](./escape.md)
Модификато `unescape` является обратным действием модификатора `escape`. Так же имеет режимы `html`, `js` and `URI`.
```smarty
{$text|unescape:$type = 'html'}
```

View File

@ -1,13 +1,13 @@
Modifier upper
Модификатор upper
==============
Modifier is used to uppercase a variable or string. Have short alias `up`.
This is equivalent to the PHP [strtoupper()](http://docs.php.net/strtoupper) function.
Переводит строку в верхний регистр. Является эквивалентом функции PHP [strtoupper()](http://docs.php.net/ru/strtoupper).
Имеет псевдоним `up`.
```smarty
{var $name = "Bzick"}
{$name} outputs Bzick
{$name|upper} outputs BZICK
{$name|up} outputs BZICK too
{$name} выводит Bzick
{$name|upper} выводит BZICK
{$name|up} выводит BZICK
```

View File

@ -1,15 +1,20 @@
Documentation
Документация
=============
### Fenom
* [Быстрый старт](./start.md)
* [Адаптеры для фрейморков](./adapters.md)
* [Для разработчиков](./dev/readme.md)
* [Нстройки](./configuration.md)
* [Синтаксис шаблонов](./syntax.md)
* [Операторы](./operators.md)
* [Разработка Fenom](./dev/readme.md)
* [Настройки](./configuration.md)
* [Синтаксис](./syntax.md)
* [Переменные](./syntax.md#Переменные)
* [Значения](./syntax.md#Скалярные-значения)
* [Массивы](./syntax.md#Массивы)
* [Операторы](./operators.md)
* [Модификаторы](./syntax.md#Модификаторы)
* [Теги](./syntax.md#Теги)
* [Параметры тегов](./syntax.md#Параметры-тегов)
***
@ -17,14 +22,14 @@ Documentation
[Использование](./syntax.md#tags) тегов.
* [var](./tags/var.md) — определение переменной
* [set](./tags/set.md), `add` и `var` — определение значения переменной
* [if](./tags/if.md), `elseif` и `else` — условный оператор
* [foreach](./tags/foreach.md), `foreaelse`, `break` and `continue` — перебор элементов массива или объекта
* [for](./tags/for.md), `forelse`, `break` and `continue` — цикл
* [switch](./tags/switch.md), `case`, `default` — груповой условный оператор
* [switch](./tags/switch.md), `case` — груповой условный оператор
* [cycle](./tags/cycle.md) — циклицеский перебор массива значений
* [include](./tags/include.md), `insert` — вставляет и испольняет указанный шаблон
* [extends](./tags/extends.md), `use`, `block` и `parent` — наследование шаблонов
* [extends](./tags/extends.md), `use`, `block` и `parent`[наследование](./inheritance.md) шаблонов
* [filter](./tags/filter.md) — примение модификаторов к фрагменту шаблона
* [ignore](./tags/ignore.md) — игнорирование тегов Fenom
* [macro](./tags/macro.md) и `import` — пользовательские функции шаблонов
@ -65,20 +70,25 @@ Documentation
### Операторы
* [Арифметические операторы](./operators.md#arithmetic-operators) — `+`, `-`, `*`, `/`, `%`
* [Логические операторы](./operators.md#logical-operators) — `||`, `&&`, `!$var`, `and`, `or`, `xor`
* [Операторы сравнения](./operators.md#comparison-operators) — `>`, `>=`, `<`, `<=`, `==`, `!=`, `!==`, `<>`
* [Битовые операторы](./operators.md#bitwise-operators) — `|`, `&`, `^`, `~$var`, `>>`, `<<`
* [Операторы присвоения](./operators.md#assignment-operators) — `=`, `+=`, `-=`, `*=`, `/=`, `%=`, `&=`, `|=`, `^=`, `>>=`, `<<=`
* [Строковый оператор](./operators.md#string-operator) — `$str1 ~ $str2`
* [Тернарные операторы](./operators.md#ternary-operators) — `$a ? $b : $c`, `$a ! $b : $c`, `$a ?: $c`, `$a !: $c`
* [Проверяющие операторы](./operators.md#check-operators) — `$var?`, `$var!`
* [Оператор тестирование](./operators.md#test-operator) — `is`, `is not`
* [Оператор содержания](./operators.md#containment-operator) — `in`, `not in`
* [Арифметические операторы](./operators.md#Арифметические-операторы) — `+`, `-`, `*`, `/`, `%`
* [Логические операторы](./operators.md#Логические-операторы) — `||`, `&&`, `!$var`, `and`, `or`, `xor`
* [Операторы сравнения](./operators.md#Операторы-сравнения) — `>`, `>=`, `<`, `<=`, `==`, `!=`, `!==`, `<>`
* [Битовые операторы](./operators.md#Битовые-операторы) — `|`, `&`, `^`, `~$var`, `>>`, `<<`
* [Операторы присвоения](./operators.md#Операторы-присвоения) — `=`, `+=`, `-=`, `*=`, `/=`, `%=`, `&=`, `|=`, `^=`, `>>=`, `<<=`
* [Строковый оператор](./operators.md#Строковый-оператор) — `$str1 ~ $str2`
* [Тернарные операторы](./operators.md#Тернарные-операторы) — `$a ? $b : $c`, `$a ! $b : $c`, `$a ?: $c`, `$a !: $c`
* [Проверяющие операторы](./operators.md#Проверяющие-операторы) — `$var?`, `$var!`
* [Оператор тестирования](./operators.md#Оператор-тестирования) — `is`, `is not`
* [Оператор содержания](./operators.md#Оператор-содержания) — `in`, `not in`
***
### Расширение
* [Источники шаблонов](./ext/extend.md#Источники-шаблонов)
* [Добавление модификаторов](./ext/extend.md#Добавление-модификаторов)
* [Добавление тегов](./ext/extend.md#Добавление-тегов)
* [Расширение тестового оператора](./ext/extend.md#Расширение-тестовго-оператора)
* [Расширение глобальной переменной](./ext/extend.md#Расширение-глобальной-переменной)
* [Расширение Fenom](./ext/extend.md)
* [Add-ons](./ext/extensions.md)

View File

@ -1,11 +1,12 @@
Basic usage
===========
Быстрый старт
=============
## Install Fenom
## Установка Fenom
### Composer
Add package Fenom in your require-list in `composer.json`:
Fenom зарегестирован на [packagist.org](https://packagist.org/) как пакет [fenom/fenom](https://packagist.org/packages/fenom/fenom).
Что бы установить Fenom через composer пропишите в `composer.json` списке пакетов:
```json
{
"require": {
@ -13,56 +14,71 @@ Add package Fenom in your require-list in `composer.json`:
}
}
```
and update project's dependencies: `composer update`.
и обновите зависимости: `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.
Склонируйте Fenom в любую директорию Вашего проекта: `git clone https://github.com/bzick/fenom.git`. Рекомендуется использовать последнюю версию.
Для загрузки классов Fenom использует [psr-0](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md#autoloading-standard) стандарт.
Таким образом вы можете:
* использовать Ваш загрузчик, который понимает `psr-0` формат для загрузки классов Fenom из директории `src/` с пространством имен `Fenom`.
* или использовать строенный загрузчик Fenom: `Fenom::registerAutoload();` для загрузки самого себя.
Also you can use this autoloader for loading any library with `psr-0` file naming:
Так же вы можете использовать встроенный в Fenom загрузчик для загрузки других классов в `psr-0` формате наименования класса и файла:
```php
Fenom::registerAutoload(PROJECT_DIR."/src");
Fenom::registerAutoload(PROJECT_DIR."/classes");
```
## Setup Fenom
## Настройка Fenom
Create an object via factory method
Есть два варианта инициировать объект шаблонизатора: через `new` оператор и фабрику.
Пример создания Fenom через фабрику:
```php
$fenom = Fenom::factory('/path/to/templates', '/path/to/compiled/template', $options);
```
Create an object via `new` operator
Пример создания Fenom через оператор `new`:
```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).
* `/path/to/templates`директория в которой хранятся шаблоны.
* `/path/to/template/cache`директория в которую Fenom будет сохранять PHP-кеш шаблонов
* `$options` - битовая маска или массив [параметров](./configuration.md).
### Use Fenom
### Использование
Что бы отобразить шаблон на экран используйте метод `display`:
Output template
```php
// $fenom->display(string $template, array $variables) : void
$fenom->display("template/name.tpl", $vars);
```
Get the result of rendering the template
Метод найдет шаблон `template/name.tpl` отрисует его в `stdout`, подставляя переменные из массива `$vars`.
Метод `fetch` возвращает вывод шаблона вместо его отображения на экран.
```php
// $fenom->fetch(string $template, array $variables) : string
$result = $fenom->fetch("template/name.tpl", $vars);
```
Create the pipeline of rendering into callback
Для отрисовки большого количества данных можно использовать поток
```php
// $fenom->pipe(string $template, array $variables, callable $callback, int $chunk_size) : void
$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
$callback = [new SplFileObject("compress.zlib:///tmp/sitemap.xml.gz", "w"), "fwrite"], // поток с архивацией в файл /tmp/sitemap.xml.gz
1e6 // размер куска данных в байтах
);
```
Поток позволяет обрабатывать большой результат по кускам, размер куска указывается в байтах аргументом `$chunk_size`.
Каждый кусок передается в `$callback` для обработки или вывода.

View File

@ -12,6 +12,8 @@
## Переменные
Переменные могут быть выведены на экран или могут быть использованы для функций, атрибутов, модификаторов внутри сложных выражений и т.д.
Переменные в Fenom представлены знаком доллара с последующим именем переменной. Имя переменной чувствительно к регистру.
Правильное имя переменной должно начинаться с буквы или символа подчеркивания и состоять из букв, цифр и символов подчеркивания в любом количестве.
### Использование переменных
@ -123,13 +125,6 @@
{"Hi, $username!"} выведет "Hi, Username!"
```
Аналогично могут быть обработаны элемент массива или свойство объекта
```smarty
{"Hi, $user.name!"}
{"Hi, $user->name!"}
```
Для чего-либо более сложного, используйте сложный синтаксис.
##### Сложный синтаксис
@ -154,8 +149,6 @@
{"Hi, {$user.name|up ~ " (admin)"}!"} выводит: Hi, USERNAME (admin)!
```
but if use single quote any template expressions will be on display as it is
#### Одинарные кавычки
Простейший способ определить строку - это заключить ее в одинарные кавычки (символ `'`).
@ -166,10 +159,10 @@ but if use single quote any template expressions will be on display as it is
это означает, что если вы попытаетесь использовать другие управляющие последовательности, такие как `\r` или `\n`, они будут выведены как есть вместо какого-либо особого поведения.
```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}"
{'Hi, $foo'} выводит 'Hi, $foo'
{'Hi, {$foo}'} выводит 'Hi, {$foo}'
{'Hi, {$user.name}'} выводит 'Hi, {$user.name}'
{'Hi, {$user.name|up}'} выводит "Hi, {$user.name|up}"
```
### Целые числа
@ -189,7 +182,11 @@ but if use single quote any template expressions will be on display as it is
```
**Замечение**
Размер целого числоа зависит от платформы, хотя, как правило, максимальное значение примерно равно 2 миллиардам (это 32-битное знаковое).
Двоичная запись числа (`0b1011011`) не доступна на старых версиях PHP — 5.3 или ниже.
Попытка исользовать на старых версия PHP приведет к исключению при компиляциях.
**Замечение**
Размер целого числа зависит от платформы, хотя, как правило, максимальное значение примерно равно 2 миллиардам (это 32-битное знаковое).
64-битные платформы обычно имеют максимальное значение около 9223372036854775807.
**Предупреждение**
@ -205,216 +202,121 @@ but if use single quote any template expressions will be on display as it is
{var $c = 7E-10}
```
### Булев
Это простейший тип. Булевое выражает истинность значения. Он может быть либо TRUE либо FALSE.
Для указания булевого значения, используйте ключевое слово TRUE или FALSE. Оба регистро-независимы.
{set $a = true}
### NULL
Специальное значение NULL представляет собой переменную без значения. NULL - это единственно возможное значение типа null.
Обычно возникают путаницы между NULL и FALSE, так как по роли они похожи, но разлицаются по принципу:
NULL - это отсутствие присутствия, а FALSE - присутвие отсутствия.
### Операции
Как и любой другой язык программирования/шаблонизации Fenom поддерживает множество различных операторов:
* [Арифметические операторы](./operators.md#arithmetic-operators) — `+`, `-`, `*`, `/`, `%`
* [Логические операторы](./operators.md#logical-operators) — `||`, `&&`, `!$var`, `and`, `or`, `xor`
* [Операторы сравнения](./operators.md#comparison-operators) — `>`, `>=`, `<`, `<=`, `==`, `!=`, `!==`, `<>`
* [Битовые операторы](./operators.md#bitwise-operators) — `|`, `&`, `^`, `~$var`, `>>`, `<<`
* [Операторы присвоения](./operators.md#assignment-operators) — `=`, `+=`, `-=`, `*=`, `/=`, `%=`, `&=`, `|=`, `^=`, `>>=`, `<<=`
* [Строковый оператор](./operators.md#string-operator) — `$str1 ~ $str2`
* [Тернарные операторы](./operators.md#ternary-operators) — `$a ? $b : $c`, `$a ! $b : $c`, `$a ?: $c`, `$a !: $c`
* [Проверяющие операторы](./operators.md#check-operators) — `$var?`, `$var!`
* [Оператор тестирование](./operators.md#test-operator) — `is`, `is not`
* [Оператор содержания](./operators.md#containment-operator) — `in`, `not in`
* Арифметические операторы — `+`, `-`, `*`, `/`, `%`
* Логические операторы — `||`, `&&`, `!$var`, `and`, `or`, `xor`
* Операторы сравнения — `>`, `>=`, `<`, `<=`, `==`, `!=`, `!==`, `<>`
* Битовые операторы — `|`, `&`, `^`, `~$var`, `>>`, `<<`
* Операторы присвоения — `=`, `+=`, `-=`, `*=`, `/=`, `%=`, `&=`, `|=`, `^=`, `>>=`, `<<=`
* Строковый оператор — `$str1 ~ $str2`
* Тернарные операторы — `$a ? $b : $c`, `$a ! $b : $c`, `$a ?: $c`, `$a !: $c`
* Проверяющие операторы — `$var?`, `$var!`
* Оператор тестирование — `is`, `is not`
* Оператор содержания — `in`, `not in`
Подробнее об [операторах](./operators.md)
Подробнее об [операторах](./operators.md).
### Set variable
## Массивы
Массив (тип array) может быть создан конструкцией `[]`. В качестве параметров она принимает любое количество разделенных запятыми пар `key => value` (`ключ => значение`).
```
[
key => value,
key2 => value2,
key3 => value3,
...
]
```
Запятая после последнего элемента массива необязательна и может быть опущена.
Обычно это делается для однострочных массивов, т.е. `[1, 2]` предпочтительней `[1, 2, ]`.
Для многострочных массивов с другой стороны обычно используется завершающая запятая, так как позволяет легче добавлять новые элементы в конец массива.
```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 *}
{set $array = [
"foo" => "bar",
"bar" => "foo",
]}
```
Using block tag
`key` может быть либо целым числом, либо строкой. `value` может быть любого типа.
Дополнительно с ключом key будут сделаны следующие преобразования:
* Строки, содержащие целое число будут преобразованы к числу. Например, ключ со значением `"8"` будет в действительности сохранен со значением `8`. С другой стороны, значение `"08"` не будет преобразовано, так как оно не является корректным десятичным целым.
* Числа с плавающей точкой также будут преобразованы к числу, т.е. дробная часть будет отброшена. Например, ключ со значением `8.7` будет в действительности сохранен со значением `8`.
* Булев также преобразовываются к целому числу. Например, ключ со значением `true` будет сохранен со значением `1` и ключ со значением `false` будет сохранен со значением `0`.
* NULL будет преобразован к пустой строке. Например, ключ со значением `null` будет в действительности сохранен со значением `""`.
* Массивы (тип array) и объекты (тип object) не могут использоваться в качестве ключей. При подобном использовании будет генерироваться предупреждение: Недопустимый тип смещения (Illegal offset type).
Если несколько элементов в объявлении массива используют одинаковый ключ, то только последний будет использоваться, а все другие будут перезаписаны.
Параметр `key` является необязательным. Если он не указан, Fenom будет использовать предыдущее наибольшее значение целочисленного ключа, увеличенное на 1.
Существующий массив может быть изменен явной установкой значений в нем.
Это выполняется присвоением значений массиву с указанием в скобках ключа или после точки.
Кроме того, используя скобки, вы можете опустить ключ.
```smarty
{var $foo}
content {$text|truncate:30}
{/var}
{var $foo|truncate:50} {* apply modifier to content *}
content {$text}
{/var}
{set $arr.key = value}
{set $arr[] = value} {* будет взят максимальный целочисленый ключ, увеличенный на 1 *}
```
Set array
Если массив `$arr` еще не существует, он будет создан. Таким образом, это еще один способ определить массив.
Однако такой способ применять не рекомендуется, так как если переменная `$arr` уже содержит некоторое значение (например, строку),
то это значение останется на месте и `[]` может на самом деле означать доступ к символу в строке. Лучше инициализировать переменную путем явного присваивания значения.
```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.
### Static method support
```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`
### 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}"
```
### Numbers
```smarty
{2|pow:10}
{var $magick = 5381|calc}
{0.2|round}
{1e-6|round}
```
## Modifiers
* Modifiers allows change some value before output or using.
* 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).
Модификаторы переменных могут быть прмменены к переменным, пользовательским функциям или строкам.
Для их применения надо после модифицируемого значения указать символ `|` (вертикальная черта) и название модификатора.
Так же модификаторы могут принимать параметры, которые влияют на их поведение.
Эти параметры следуют за названием модификатора и разделяются `:` (двоеточием).
Кроме того, по умолчанию все функции PHP могут быть использованы в качестве модификаторов (что можно отключить в настройках) и модификаторы можно комбинировать.
```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 "..."
{$foo|upper} выведет "USER"
{$foo|lower} выведет "user"
{"{$foo|lower}"} выведет "user"
{"User"|lower}} выведет "user"
{$looong_text|truncate:80:"..."} обрежет текст до 80 символов и добавит символы "..."
{$looong_text|lower|truncate:$settings.count:$settings.etc}
{var $foo="Ivan"|upper} sets $foo value "USER"
{set $foo="Ivan"|upper} значение переменной $foo будет "USER"
```
[List of modifiers](./main.md#modifiers)
## Теги
## Tags
Все сущности шаблона можно разжелить на две группы:
Basically, tag seems like
* заполнитель (placeholder) — вывод переменной в шаблоне, например `{$name}`
* тег — конструкция выполняющаяя некоторые действия, выглядит как именованный заполнитель (placeholder), например `{include $name}`
```smarty
{FUNCNAME attr1 = "val1" attr2 = $val2}
```
Теги так же можно разделить на две группы:
Tags starts with name and may have attributes
* Функии. Тег функции вызывает пользовательскую во время выполнения шаблона, результат функции будет выведен вместо тега.
Пользовательские функции являются дополнительными и могут быть индивидуальными. Они могут быть изменены по вашему желанию, также вы можете создать новые.
* Компиляторы. В отличии от функций компиляторы вызываются во время компиляции шаблона и возвращают PHP код, который описывает некоторое действие.
Компиляторы и формируют основные конструкции типа `if`, `foreach` и т.д.
Это общий формат функций, но могут быть исключения, например функция [{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}
```
### Ignoring template code
### Игнорирование кода
В шаблонизаторе Fenom используются фигурные скобки для отделения HTML от кода Fenom.
Если требуется вывести текст, содержащий фигурные скобки, то есть следующие варианты это сделать:
@ -459,7 +361,7 @@ Outputs
</script>
```
### Whitespaces
### Пробелы
Шаблонизатор допускает любое количество пробелов или переносов строк в своём коде
@ -483,14 +385,14 @@ Outputs
{/foreach}
```
### Tag options
### Параметры тегов
| 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 |
| имя | код | тип тега | описание |
| ------- | ---- | --------- | ------------ |
| strip | s | блокоый | активирует удаление лишних пробелов на подобии модфикатора `strip` |
| ignore | i | блокоый | парсер будет игнорировать любой Fenom синтаксис на контент блокового тега |
| raw | a | любой | отключает экранирование |
| escape | e | любой | принудительно активирует экранирование |
```smarty
{script:ignore} ... {/script}

View File

@ -1,14 +1,14 @@
Tag {autoescape}
=====================
Тег {autoescape}
================
Force enable or disable `auto_escape` option for block area:
Задает индивидуальное значение параметра `auto_escape` на фрагмент шаблона:
```smarty
{autoescape true}
...
Text: {$text} {* value of the variable $text will be escaped *}
Text: {$text} {* значение переменной $text будет заэкранированно *}
...
{/autoescape}
```
Also see {raw} tag and :raw tag option
Так же смотите тег [{raw}](./raw.md) и параметр тега [:raw](../configuration.md)

View File

@ -1,14 +1,12 @@
Tag {autotrim}
Тег {autotrim}
==============
Force enable or disable `auto_trim` option for block area:
Задает индивидуальное значение параметра `auto_trim` на фрагмент шаблона:
```smarty
{autotrim true}
...
Text: {$text} {* value of the variable $text will be escaped *}
Text: {$text}
...
{/autotrim}
```
Also see :trim, :rtrim and :ltrim tag options

View File

@ -1,13 +1,16 @@
Tag {cycle}
Тег {cycle}
===========
Тег {cycle} используется для прохода через множество значений.
С его помощью можно легко реализовать чередование двух или более заданных значений.
```smarty
{for $i=$a.c..}
{for $i=1 to=6}
<div class="{cycle ["odd", "even"]}">
{/for}
{for $i=$a.c..}
{for $i=1 to=6}
<div class="{cycle ["odd", "even"] index=$i}">
{/for}
```

View File

@ -1,7 +1,7 @@
Tag {extends} [RU]
==================
Тег {extends}
=============
Тег `{extends}` реализует наследование шаблонов, иерархия, обратная {include}. То есть шаблон сам выбирает своего родителя.
Тег `{extends}` реализует [наследование](../inheritance.md) шаблонов, иерархия, обратная {include}. То есть шаблон сам выбирает своего родителя.
### {extends}
@ -11,15 +11,15 @@ Tag {extends} [RU]
{extends 'parent.tpl'}
```
Имя родительского шаблона может быть задан динамически, в этом случае производительность отрисовки может снизиться.
**Замечание:**
Имя родительского шаблона может быть задан динамически, но в этом случае производительность шаблона значительно снижается.
```smarty
{extends $parent_tpl}
```
### {block}
Блок указывает фрагмент шаблона, который будет передан родителю. Имя блока может быть задано как явно
Блок указывает фрагмент шаблона, который будет передан родителю. Имя блока должно быть задано явно:
```smarty
{block bk1}content 1{/block}
@ -27,17 +27,6 @@ Tag {extends} [RU]
{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}
@ -47,36 +36,12 @@ Tag {extends} [RU]
{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 } заданы **не** явно, с использованием переменных и условий.
* Имена блоков заданы **не** явно, с использованием переменных, условий или могут быть вложенные в другие теги.
Режим может идти только на понижение, при изменении условий во время прохождения по иерархии шаблонов.
При любом режиме работы не используется буферизация данных, то есть данные выводятся сразу.
```

View File

@ -1,7 +1,7 @@
Tags {filter}
Тег {filter}
=============
Позволяет применить модификаторы на фрагмент шаблона
Тег {filter} позволяет применить модификаторы на фрагмент шаблона
```smarty
{filter|strip_tags|truncate:20}

View File

@ -1,4 +1,4 @@
Tag {for}
Тег {for}
=========
```smarty

View File

@ -1,5 +1,7 @@
Tag {foreach} [RU]
==================
Тег {foreach}
=============
Тег `foreach` предоставляет простой способ перебора массивов.
```smarty
{foreach $list as [$key =>] $value [index=$index] [first=$first] [last=$last]}
@ -81,6 +83,5 @@ Tag {foreach} [RU]
В блоке `{foreachelse}...{/foreach}` использование `{break}`, `{continue}` выбросит исключение `Fenom\CompileException` при компиляции
### Notice
**Замечание:**
Использование last требует от `$list` быть **countable**.

View File

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

View File

@ -1,9 +1,9 @@
Tag {ignore}
Тег {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.
Теги `{ignore}{/ignore}` позволяют игнорировать заключенные в них другие теги.
Весь текст внутри тегов `{ignore}{/ignore}` не интерпретируется, а выводится "как есть".
Обычно они используются вместе с javascript или таблицами стилей, в которых фигурные скобки конфликтуют с синтаксисом разделителей.
```smarty
{ignore}
@ -11,8 +11,8 @@ Anything within {ignore}{/ignore} tags is not interpreted, but displayed as-is.
{/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:
Использование тегов {ignore} не всегда обязательное так как Fenom игнорирует фигурные скобки `{` сразу после которых идут пробельные символы.
Убедитесь что открывающие фигурные скобки в JavaScript и CSS имеют хотя бы по пробелу справа:
```smarty
var data = { "time": obj.ts };

View File

@ -1,29 +1,35 @@
Tag {include}
Тег {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.
Тэги `{include}` используются для включения других шаблонов в текущий. Любые переменные, доступные в текущем шаблоне, доступны и во включаемом.
```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}
{include "pagination.tpl" count=$total_pages current=$.get.page}
```
All variables changed in child template has no affect to variables in parent template.
Все значения присвоенных переменных восстанавливаются после того, как подключаемый шаблон отработал.
Это значит, что вы можете использовать все переменные из подключающего шаблона в подключаемом, но изменения переменных внутри подключаемого шаблона не будут видны внутри подключающего шаблона после команды {include}.
### {insert}
The tag insert template code instead self.
В отличии от `{include}` тег `{insert}` не вызывает дочерний шаблон во время отрисовки, в ставляет код дочернего шаблона в родительский на момент компиляции.
Это позволяет сэкономить ресурсы на проверке и чтении шаблона. Однако такой формат подключения шаблона имеет ограничения.
Имя шаблона должно быть задано явно, без использования переменных и выражений:
* No dynamic name allowed.
* No variables as attribute allowed.
* Increase performance because insert code as is in compilation time.
```smarty
{insert 'pagination.tpl'} {* отработает *}
{insert $pagination} {* вызовет ошибку *}
```
For example, main.tpl:
Рассмотрим тега `{insert}` на примере. Допустим шаблон `main.tpl` имеет следующий код:
```smarty
a: {$a}
@ -31,13 +37,13 @@ a: {$a}
c: {$c}
```
b.tpl:
`b.tpl`:
```
b: {$b}
```
Code of `b.tpl` will be inserted into `main.tpl` as is:
Компилятор увидит шаблон `main.tpl` таким:
```smarty
a: {$a}

View File

@ -1,5 +1,5 @@
Tag {macro} [RU]
================
Тег {macro}
===========
Макросы - фрагмент шаблона который можно повторить сколь угодно раз и в каком угодно месте.
Макросы не имеют общего пространства имен с шаблоном и могут оперировать только переданными переменными.

View File

@ -1,8 +1,8 @@
Tag {raw}
Тег {raw}
=========
Tag `{raw <expression>}` allow outputs render results without escaping.
This tag rewrite global option `auto_escape` for specified code.
Тег `{raw <expression>}` позволяет вывести результат выражения без экранирования.
```smarty
{autoescape true}
@ -16,7 +16,7 @@ This tag rewrite global option `auto_escape` for specified code.
{/autoescate}
```
For functions use tag with prefix `raw:`:
Для функций используйте параметр тега `:raw`:
```smarty
{autoescape true}
@ -25,6 +25,4 @@ For functions use tag with prefix `raw:`:
{my_func:raw page=5} {* unescape *}
...
{/autoescape}
```
Tag can not be applied to compilers as `foreach`, `if` and other.
```

81
docs/ru/tags/set.md Normal file
View File

@ -0,0 +1,81 @@
Тег {set}
=========
### {set}
Тег {set} используется для установки значения переменной в процессе выполнения шаблона.
```smarty
{set $var=(expr)}
```
```smarty
{set $var}
... any content ...
{/set}
```
```smarty
{set $var|modifiers}
... any content ...
{/set}
```
Имя переменной `$var` должно соответствовать [принятому правилу именования переменных](../syntax.md#Переменные).
Выражение `expr` может быть любое сочетание [переменных](../syntax.md#Переменные), [скалярных значений](../syntax.md#Скалярные+значения) и массивов.
```smarty
{set $v = 5}
{set $v = "value"}
{set $v = $x+$y}
{set $v = 4}
{set $v = $z++ + 1}
{set $v = --$z}
{set $v = $y/$x}
{set $v = $y-$x}
{set $v = $y*$x-2}
{set $v = ($y^$x)+7}
{set $v = [1,2,3]}
{set $v = []}
{set $v = ["one"|upper => 1, 4 => $x, "three" => 3]}
{set $v = ["key1" => $y*$x-2, "key2" => ["z" => $z]]}
{set $v = count([1,2,3])+7}
```
В качестве значения переменной можно задать результат отрисовки фрагмента шаблона:
```smarty
{set $v}
Some long {$text|trim}
{/var}
```
Такой вариант создания позволяет применить модификаторы к данным переде тем как они будут сохранены в переменную:
```smarty
{set $v|escape} {* применение можификатора к значению *}
Some long {$text|trim}
{/var}
```
### {add}
Тег {add} делает тоже самое что и тег {set} за исключением того что сначало проверяет наличие переменной и если переменной нет — задет новое значение.
```smarty
{add $var = 'value'}
```
Работу тега можнно описать следующим образом:
```smarty
{if $var is not set}
{set $var = 'value'}
{/if}
```
### {var}
Тег {var} старое название тега {set}, сейчас это одно и тоже.

View File

@ -1,46 +1,61 @@
Tag {switch}
Тег {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.
Тег `{switch}` подобен серии операторов `{if}` с одинаковым условием.
Во многих случаях вам может понадобиться сравнивать одну и ту же переменную (или выражение) с множеством различных значений,
и выполнять различные участки кода в зависимости от того, какое значение принимает эта переменная (или выражение).
Это именно тот случай, для которого удобен тег `{switch}`.
Tag `{switch}` accepts any expression. But `{case}` accepts only static scalar values or constants.
Тег `{switch}` в качестве аргумента принимает любое выражение.
Каждый возможный случай описывается тегом `{case value}` значения `value` которых могут быть только явно заданные скалярные значения.
Случаи могут повторятся, в этом случае блоки для которых повторялся случай будут последовательно выполнены по направлению сверху вниз.
Случай `default` подразумевает обработку если ни один случай не произошел.
```smarty
{switch <condition>}
{case <value1>}
{case value1}
...
{case <value2>, <value3>, ...}
{case value2, value3, ...}
...
{case <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 $color}
{case 'red', 'scarlet'}
Оттенок красного цвета
{case 'green', 'harlequin'}
Оттенок зеленого цвета
{case 'black', 'grey', 'gray'}
Черный цвет
{case 'white', 'grey', 'gray'}
Белый цвет
{case default, 'unknown'}
Неизвестный цвет
{/switch}
```
if `$type = 'new'` then template output
если задать `$color = 'red'` результатом будет:
```
It is new item
It is new or current item
It is new item, again
Оттенок красного цвета
```
для случая `$color = 'grey'` будут вызваны два бока:
```
Черный цвет
Белый цвет
```
случаи `$color = 'yellow'` и `$color = 'unknown'` будут обработаны последним блоком:
```
Неизвестный цвет
```

View File

@ -1,12 +1,12 @@
Tag {unset}
Тег {unset}
===========
Unset a given variables.
Удаляет переменные.
```smarty
{unset $a} unset single variable
{unset $a} единичное удаление
{unset $a $b $c.d.e} multiple unset
{unset $a $b $c.d.e} множественное удаление
```

View File

@ -1,64 +0,0 @@
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}
```

View File

@ -229,10 +229,20 @@ class Fenom
'type' => self::INLINE_COMPILER,
'parser' => 'Fenom\Compiler::tagInsert'
),
'var' => array( // {var ...}
'var' => array( // {var ...}
'type' => self::BLOCK_COMPILER,
'open' => 'Fenom\Compiler::varOpen',
'close' => 'Fenom\Compiler::varClose'
'open' => 'Fenom\Compiler::setOpen',
'close' => 'Fenom\Compiler::setClose'
),
'set' => array( // {set ...}
'type' => self::BLOCK_COMPILER,
'open' => 'Fenom\Compiler::setOpen',
'close' => 'Fenom\Compiler::setClose'
),
'add' => array( // {add ...}
'type' => self::BLOCK_COMPILER,
'open' => 'Fenom\Compiler::setOpen',
'close' => 'Fenom\Compiler::setClose'
),
'block' => array( // {block ...} {parent} {/block}
'type' => self::BLOCK_COMPILER,

View File

@ -740,23 +740,32 @@ class Compiler
* @param Tag $scope
* @return string
*/
public static function varOpen(Tokenizer $tokens, Tag $scope)
public static function setOpen(Tokenizer $tokens, Tag $scope)
{
$var = $scope->tpl->parseVariable($tokens);
if ($tokens->is('=')) { // inline tag {var ...}
$before = $after = "";
if($scope->name == 'add') {
$before = "if(!isset($var)) {\n";
$after = "\n}";
}
if ($tokens->is(Tokenizer::MACRO_EQUALS, '[')) { // inline tag {var ...}
$equal = $tokens->getAndNext();
if($equal == '[') {
$tokens->need(']')->next()->need('=')->next();
$equal = '[]=';
}
$scope->close();
$tokens->next();
if ($tokens->is("[")) {
return $var . '=' . $scope->tpl->parseArray($tokens);
return $before.$var . $equal . $scope->tpl->parseArray($tokens) . ';'.$after;
} else {
return $var . '=' . $scope->tpl->parseExpr($tokens);
return $before.$var . $equal . $scope->tpl->parseExpr($tokens) . ';'.$after;
}
} else {
$scope["name"] = $var;
if ($tokens->is('|')) {
$scope["value"] = $scope->tpl->parseModifier($tokens, "ob_get_clean()");
$scope["value"] = $before . $scope->tpl->parseModifier($tokens, "ob_get_clean()").';'.$after;
} else {
$scope["value"] = "ob_get_clean()";
$scope["value"] = $before . "ob_get_clean();" . $after;
}
return 'ob_start();';
}
@ -767,7 +776,7 @@ class Compiler
* @param Tag $scope
* @return string
*/
public static function varClose(Tokenizer $tokens, Tag $scope)
public static function setClose(Tokenizer $tokens, Tag $scope)
{
return $scope["name"] . '=' . $scope["value"] . ';';
}

View File

@ -693,11 +693,15 @@ class Template extends Render
$cond = false;
}
$op = $tokens->getAndNext();
} elseif ($tokens->is(Tokenizer::MACRO_EQUALS)) { // assignment operator: $a = 4, $a += 3, ...
} elseif ($tokens->is(Tokenizer::MACRO_EQUALS, '[')) { // assignment operator: $a = 4, $a += 3, ...
if (!$var) {
break;
}
$op = $tokens->getAndNext();
if($op == '[') {
$tokens->need(']')->next()->need('=')->next();
$op = '[]=';
}
} elseif ($tokens->is(T_STRING)) { // test or containment operator: $a in $b, $a is set, ...
if (!$exp) {
break;
@ -866,6 +870,9 @@ class Template extends Render
}
$var .= $key;
} elseif ($t === "[") {
if($tokens->isNext(']')) {
break;
}
$tokens->next();
if ($tokens->is(Tokenizer::MACRO_STRING)) {
if ($tokens->isNext("(")) {

View File

@ -241,7 +241,6 @@ class Tokenizer
\T_SR_EQUAL => 1,
\T_XOR_EQUAL => 1,
'=' => 1,
// \T_CONCAT_EQUAL => 1,
),
self::MACRO_SCALAR => array(
\T_LNUMBER => 1,

View File

@ -122,9 +122,11 @@ class TemplateTest extends TestCase
{
return array(
array('hello, {$a.}!', 'Fenom\Error\CompileException', "Unexpected end of expression"),
array('hello, {$b[}!', 'Fenom\Error\CompileException', "Unexpected end of expression"),
array('hello, {$b.}!', 'Fenom\Error\CompileException', "Unexpected end of expression"),
array('hello, {$b[c}!', 'Fenom\Error\CompileException', "Unexpected end of expression"),
array('hello, {$b.c]}!', 'Fenom\Error\CompileException', "Unexpected token ']'"),
array('hello, {$b[ ]}!', 'Fenom\Error\CompileException', "Unexpected token ']'"),
array('hello, {$b[ ]}!', 'Fenom\Error\CompileException', "Unexpected end of expression"),
array('hello, {$b[9/].c}!', 'Fenom\Error\CompileException', "Unexpected token ']'"),
array('hello, {$b[3]$c}!', 'Fenom\Error\CompileException', "Unexpected token '\$c'"),
array('hello, {$b[3]c}!', 'Fenom\Error\CompileException', "Unexpected token 'c'"),
@ -471,40 +473,42 @@ class TemplateTest extends TestCase
"z" => 99
);
return array(
array('Create: {var $v = $x+$y} Result: {$v} end', $a, 'Create: Result: 36 end'),
array('Create: {set $v = $x+$y} Result: {$v} end', $a, 'Create: Result: 36 end'),
array('Create: {add $x = $x+$y} Result: {$x} end', $a, 'Create: Result: 9 end'),
array('Create: {add $v = 3} {add $v = 9} Result: {$v} end', $a, 'Create: Result: 3 end'),
array(
'Create: {var $v =
'Create: {set $v =
$x
+
$y} Result: {$v} end',
$a,
'Create: Result: 36 end'
),
array('Create: {var $v = $z++} Result: {$v}, {$z} end', $a, 'Create: Result: 99, 100 end'),
array('Create: {var $v = $z++ + 1} Result: {$v}, {$z} end', $a, 'Create: Result: 100, 100 end'),
array('Create: {var $v = --$z} Result: {$v}, {$z} end', $a, 'Create: Result: 98, 98 end'),
array('Create: {var $v = $y/$x} Result: {$v} end', $a, 'Create: Result: 3 end'),
array('Create: {var $v = $y-$x} Result: {$v} end', $a, 'Create: Result: 18 end'),
array('Create: {var $v = $y*$x-2} Result: {$v} end', $a, 'Create: Result: 241 end'),
array('Create: {var $v = ($y^$x)+7} Result: {$v} end', $a, 'Create: Result: 25 end'),
array('Create: {var $v = [1,2,3]} Result: {$v.1} end', $a, 'Create: Result: 2 end'),
array('Create: {set $v = $z++} Result: {$v}, {$z} end', $a, 'Create: Result: 99, 100 end'),
array('Create: {set $v = $z++ + 1} Result: {$v}, {$z} end', $a, 'Create: Result: 100, 100 end'),
array('Create: {set $v = --$z} Result: {$v}, {$z} end', $a, 'Create: Result: 98, 98 end'),
array('Create: {set $v = $y/$x} Result: {$v} end', $a, 'Create: Result: 3 end'),
array('Create: {set $v = $y-$x} Result: {$v} end', $a, 'Create: Result: 18 end'),
array('Create: {set $v = $y*$x-2} Result: {$v} end', $a, 'Create: Result: 241 end'),
array('Create: {set $v = ($y^$x)+7} Result: {$v} end', $a, 'Create: Result: 25 end'),
array('Create: {set $v = [1,2,3]} Result: {$v.1} end', $a, 'Create: Result: 2 end'),
array(
'Create: {var $v = []} Result: {if $v} have items {else} empty {/if} end',
'Create: {set $v = []} Result: {if $v} have items {else} empty {/if} end',
$a,
'Create: Result: empty end'
),
array(
'Create: {var $v = ["one"|upper => 1, 4 => $x, "three" => 3]} Result: {$v.three}, {$v.4}, {$v.ONE} end',
'Create: {set $v = ["one"|upper => 1, 4 => $x, "three" => 3]} Result: {$v.three}, {$v.4}, {$v.ONE} end',
$a,
'Create: Result: 3, 9, 1 end'
),
array(
'Create: {var $v = ["key1" => $y*$x-2, "key2" => ["z" => $z]]} Result: {$v.key1}, {$v.key2.z} end',
'Create: {set $v = ["key1" => $y*$x-2, "key2" => ["z" => $z]]} Result: {$v.key1}, {$v.key2.z} end',
$a,
'Create: Result: 241, 99 end'
),
array(
'Create: {var $v = count([1,2,3])+7} Result: {$v} end',
'Create: {set $v = count([1,2,3])+7} Result: {$v} end',
$a,
'Create: Result: 10 end'
),
@ -514,58 +518,59 @@ class TemplateTest extends TestCase
public static function providerCreateVarInvalid()
{
return array(
array('Create: {var $v} Result: {$v} end', 'Fenom\Error\CompileException', "Unclosed tag: {var} opened"),
array('Create: {set $v} Result: {$v} end', 'Fenom\Error\CompileException', "Unclosed tag: {set} opened"),
array('Create: {add $v} Result: {$v} end', 'Fenom\Error\CompileException', "Unclosed tag: {add} opened"),
array(
'Create: {var $v = } Result: {$v} end',
'Create: {set $v = } Result: {$v} end',
'Fenom\Error\CompileException',
"Unexpected end of expression"
),
array('Create: {var $v = 1++} Result: {$v} end', 'Fenom\Error\CompileException', "Unexpected token '++'"),
array('Create: {var $v = c} Result: {$v} end', 'Fenom\Error\CompileException', "Unexpected token 'c'"),
array('Create: {set $v = 1++} Result: {$v} end', 'Fenom\Error\CompileException', "Unexpected token '++'"),
array('Create: {set $v = c} Result: {$v} end', 'Fenom\Error\CompileException', "Unexpected token 'c'"),
array(
'Create: {var $v = ($a)++} Result: {$v} end',
'Create: {set $v = ($a)++} Result: {$v} end',
'Fenom\Error\CompileException',
"Unexpected token '++'"
),
array(
'Create: {var $v = --$a++} Result: {$v} end',
'Create: {set $v = --$a++} Result: {$v} end',
'Fenom\Error\CompileException',
"Unexpected token '++'"
),
array(
'Create: {var $v = $a|upper++} Result: {$v} end',
'Create: {set $v = $a|upper++} Result: {$v} end',
'Fenom\Error\CompileException',
"Unexpected token '++'"
),
array(
'Create: {var $v = max($a,2)++} Result: {$v} end',
'Create: {set $v = max($a,2)++} Result: {$v} end',
'Fenom\Error\CompileException',
"Unexpected token '++'"
),
array(
'Create: {var $v = max($a,2)} Result: {$v} end',
'Create: {set $v = max($a,2)} Result: {$v} end',
'Fenom\Error\CompileException',
"Function max not found",
Fenom::DENY_NATIVE_FUNCS
),
array(
'Create: {var $v = 4*} Result: {$v} end',
'Create: {set $v = 4*} Result: {$v} end',
'Fenom\Error\CompileException',
"Unexpected end of expression"
),
array('Create: {var $v = ""$a} Result: {$v} end', 'Fenom\Error\CompileException', "Unexpected token '\$a'"),
array('Create: {set $v = ""$a} Result: {$v} end', 'Fenom\Error\CompileException', "Unexpected token '\$a'"),
array(
'Create: {var $v = [1,2} Result: {$v} end',
'Create: {set $v = [1,2} Result: {$v} end',
'Fenom\Error\CompileException',
"Unexpected end of expression"
),
array(
'Create: {var $v = empty(2)} Result: {$v} end',
'Create: {set $v = empty(2)} Result: {$v} end',
'Fenom\Error\CompileException',
"Unexpected token 2, isset() and empty() accept only variables"
),
array(
'Create: {var $v = isset(2)} Result: {$v} end',
'Create: {set $v = isset(2)} Result: {$v} end',
'Fenom\Error\CompileException',
"Unexpected token 2, isset() and empty() accept only variables"
),
@ -576,32 +581,33 @@ class TemplateTest extends TestCase
public static function providerArrays()
{
return array(
array('{var $arr = []}', array()),
array('{var $arr = [1]}', array(1)),
array('{var $arr = [1,]}', array(1)),
array('{var $arr = [1, 2, 3, 5]}', array(1, 2, 3, 5)),
array('{var $arr = [1, true, false, null, -1, 1.1, -2.2, 5, "str"]}', array(1, true, false, null, -1, 1.1, -2.2, 5, "str")),
array('{var $arr = [5 => 1, "two" => 2, 3]}', array(5 => 1, "two" => 2, 3)),
array('{var $arr = [1 + 1, 2 * 2, 3 / 3 + 7,]}', array(1 + 1, 2 * 2, 3 / 3 + 7)),
array('{var $arr = [$zero, $two => $one, $num.3 => $.const.PHP_VERSION]}', array(0, 2 => 1, "three" => PHP_VERSION)),
array('{var $arr = [5 - 1 => 1, "two"|up => "two"|low, 3 => count([1,2])]}', array(4 => 1, "TWO" => "two", 3 => 2)),
array('{set $arr[] = 4}', array(4)),
array('{set $arr = []}', array()),
array('{set $arr = [1]}', array(1)),
array('{set $arr = [1,]}', array(1)),
array('{set $arr = [1, 2, 3, 5]}', array(1, 2, 3, 5)),
array('{set $arr = [1, true, false, null, -1, 1.1, -2.2, 5, "str"]}', array(1, true, false, null, -1, 1.1, -2.2, 5, "str")),
array('{set $arr = [5 => 1, "two" => 2, 3]}', array(5 => 1, "two" => 2, 3)),
array('{set $arr = [1 + 1, 2 * 2, 3 / 3 + 7,]}', array(1 + 1, 2 * 2, 3 / 3 + 7)),
array('{set $arr = [$zero, $two => $one, $num.3 => $.const.PHP_VERSION]}', array(0, 2 => 1, "three" => PHP_VERSION)),
array('{set $arr = [5 - 1 => 1, "two"|up => "two"|low, 3 => count([1,2])]}', array(4 => 1, "TWO" => "two", 3 => 2)),
array('{var $arr = [[1]]}', array(array(1))),
array('{var $arr = [[],[]]}', array(array(),array())),
array('{var $arr = [1, [2, 3], 5]}', array(1, array(2, 3), 5)),
array('{var $arr = [1, [true, false, null, -1, 1.1, -2.2, 5], "str"]}', array(1, array(true, false, null, -1, 1.1, -2.2, 5), "str")),
array('{var $arr = [5 => [1, "two" => 2], 3]}', array(5 => array(1, "two" => 2), 3)),
array('{var $arr = [1 + 1, [2 * 2, 3 / 3 + 7,],]}', array(1 + 1, array(2 * 2, 3 / 3 + 7))),
array('{var $arr = [$zero, [$two => $one, $num.3 => $.const.PHP_VERSION]]}', array(0, array(2 => 1, "three" => PHP_VERSION))),
array('{var $arr = [5 - 1 => 1, ["two"|up => ("two"|low ~ "..."), 3 => count([1,2])]]}', array(4 => 1, array("TWO" => "two...", 3 => 2))),
array('{set $arr = [[1]]}', array(array(1))),
array('{set $arr = [[],[]]}', array(array(),array())),
array('{set $arr = [1, [2, 3], 5]}', array(1, array(2, 3), 5)),
array('{set $arr = [1, [true, false, null, -1, 1.1, -2.2, 5], "str"]}', array(1, array(true, false, null, -1, 1.1, -2.2, 5), "str")),
array('{set $arr = [5 => [1, "two" => 2], 3]}', array(5 => array(1, "two" => 2), 3)),
array('{set $arr = [1 + 1, [2 * 2, 3 / 3 + 7,],]}', array(1 + 1, array(2 * 2, 3 / 3 + 7))),
array('{set $arr = [$zero, [$two => $one, $num.3 => $.const.PHP_VERSION]]}', array(0, array(2 => 1, "three" => PHP_VERSION))),
array('{set $arr = [5 - 1 => 1, ["two"|up => ("two"|low ~ "..."), 3 => count([1,2])]]}', array(4 => 1, array("TWO" => "two...", 3 => 2))),
);
}
public static function providerUnset() {
return array(
array('{var $a = 5} {unset $a} {if $a is not set}not set{/if}', 'not set'),
array('{var $a = ["b" => 5, "c" => 6]} {unset $a.b} {if $a.b is not set}not set{/if} but c is {$a.c}', 'not set but c is 6'),
array('{var $a = ["b" => 5, "c" => 6]} {unset $a.b $a.c} {if $a.b is not set}not set{/if} {if $a.c is not set}not set{/if}', 'not set not set'),
array('{set $a = 5} {unset $a} {if $a is not set}not set{/if}', 'not set'),
array('{set $a = ["b" => 5, "c" => 6]} {unset $a.b} {if $a.b is not set}not set{/if} but c is {$a.c}', 'not set but c is 6'),
array('{set $a = ["b" => 5, "c" => 6]} {unset $a.b $a.c} {if $a.b is not set}not set{/if} {if $a.c is not set}not set{/if}', 'not set not set'),
);
}
@ -1104,7 +1110,7 @@ class TemplateTest extends TestCase
"Template multi-extended by block1"
),
array(
'{extends "parent.tpl"}{var $bk = "bk3"}{block "bk1"} block1 {/block}{block "bk2"} block2 {/block} {block "$bk"} block3 {/block} garbage',
'{extends "parent.tpl"}{set $bk = "bk3"}{block "bk1"} block1 {/block}{block "bk2"} block2 {/block} {block "$bk"} block3 {/block} garbage',
"Template multi-extended by block1"
),
);
@ -1312,7 +1318,7 @@ class TemplateTest extends TestCase
try {
var_dump(
$this->fenom->compileCode(
'{unset $a $a.c $b}'
'{add $a[] = 5}'
)->getBody()
);
} catch (\Exception $e) {