mirror of
https://github.com/fenom-template/fenom.git
synced 2023-08-10 21:13:07 +03:00
Merge branch 'origin/master'
This commit is contained in:
commit
2cc9ffdf62
@ -1,7 +1,14 @@
|
|||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
## 2.0.0RC1
|
### 2.0.1 (2013-06-09)
|
||||||
|
|
||||||
|
- Fix string concatenation. If `~` in the end of expression Fenom generates broken template.
|
||||||
|
- Fix `~=` operator. Operator was not working.
|
||||||
|
- Tests++
|
||||||
|
- Docs++
|
||||||
|
|
||||||
|
## 2.0.0
|
||||||
|
|
||||||
- Add tag the {filter}
|
- Add tag the {filter}
|
||||||
- Redesign `extends` algorithm:
|
- Redesign `extends` algorithm:
|
||||||
|
10
README.md
10
README.md
@ -2,11 +2,11 @@ Fenom - Template Engine for PHP
|
|||||||
===============================
|
===============================
|
||||||
|
|
||||||
> Composer [package](https://packagist.org/packages/fenom/fenom): `{"fenom/fenom": "2.*"}`. <br />
|
> Composer [package](https://packagist.org/packages/fenom/fenom): `{"fenom/fenom": "2.*"}`. <br />
|
||||||
> For old version: `{"fenom/fenom": "1.*"}`. [List](https://github.com/bzick/fenom/wiki/Migrate-from-1.*-to-2.*) of incompatibilities between 1.* and 2.* versions.
|
> For old version: `{"fenom/fenom": "1.*"}`. [List](https://github.com/bzick/fenom/wiki/Migrate-from-1.4.9-to-2.0) of incompatibilities between 1.* and 2.* versions.
|
||||||
|
|
||||||
[![Latest Stable Version](https://poser.pugx.org/fenom/fenom/v/stable.png)](https://packagist.org/packages/fenom/fenom)
|
[![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=develop)](https://travis-ci.org/bzick/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=develop)](https://coveralls.io/r/bzick/fenom?branch=master)
|
[![Coverage Status](https://coveralls.io/repos/bzick/fenom/badge.png?branch=master)](https://coveralls.io/r/bzick/fenom?branch=master)
|
||||||
[![Total Downloads](https://poser.pugx.org/fenom/fenom/downloads.png)](https://packagist.org/packages/fenom/fenom)
|
[![Total Downloads](https://poser.pugx.org/fenom/fenom/downloads.png)](https://packagist.org/packages/fenom/fenom)
|
||||||
## [Quick start](./docs/start.md) :: [Documentation](./docs/readme.md) :: [Benchmark](./docs/benchmark.md)
|
## [Quick start](./docs/start.md) :: [Documentation](./docs/readme.md) :: [Benchmark](./docs/benchmark.md)
|
||||||
<!-- :: [Articles](./docs/articles.md) -->
|
<!-- :: [Articles](./docs/articles.md) -->
|
||||||
@ -15,7 +15,7 @@ Fenom - Template Engine for PHP
|
|||||||
|
|
||||||
**Fenom** *(from "fenomenal")* — lightweight template engine for PHP.
|
**Fenom** *(from "fenomenal")* — lightweight template engine for PHP.
|
||||||
|
|
||||||
It mean:
|
It means:
|
||||||
|
|
||||||
* Known Smarty-like [syntax](./docs/syntax.md) with improvements.
|
* Known Smarty-like [syntax](./docs/syntax.md) with improvements.
|
||||||
* Very [fast](./docs/benchmark.md).
|
* Very [fast](./docs/benchmark.md).
|
||||||
@ -23,7 +23,7 @@ It mean:
|
|||||||
* Very [flexible](./docs/configuration.md#extends).
|
* Very [flexible](./docs/configuration.md#extends).
|
||||||
* Progressive parser without regular expressions.
|
* Progressive parser without regular expressions.
|
||||||
* High [code coverage](https://coveralls.io/r/bzick/fenom?branch=master).
|
* High [code coverage](https://coveralls.io/r/bzick/fenom?branch=master).
|
||||||
* Easy to understand [how it works](./docs/dev.md).
|
* Easy to understand [how it works](./docs/dev/readme.md).
|
||||||
* Easy to [use](./docs/start.md).
|
* Easy to [use](./docs/start.md).
|
||||||
* Maximum [protection](./docs/configuration.md#configure).
|
* Maximum [protection](./docs/configuration.md#configure).
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ Options may by associative array like `'option_name' => true` or bitwise mask.
|
|||||||
| *force_verify* | `Fenom::FORCE_VERIFY` | check existence every used variable | 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 | | -->
|
<!-- | *auto_trim* | `Fenom::AUTO_TRIM` | remove space-characters before and after tags | | -->
|
||||||
| *disable_statics* | `Fenom::DENY_STATICS` | disable calling static methods in templates. | |
|
| *disable_statics* | `Fenom::DENY_STATICS` | disable calling static methods in templates. | |
|
||||||
| *strip* | `Fenom::STRIP` | strip all whitespaces in templates. | decrease cache size |
|
| *strip* | `Fenom::AUTO_STRIP` | strip all whitespaces in templates. | decrease cache size |
|
||||||
|
|
||||||
```php
|
```php
|
||||||
$fenom->setOptions(array(
|
$fenom->setOptions(array(
|
||||||
@ -50,46 +50,12 @@ By default all options disabled
|
|||||||
|
|
||||||
## Extends
|
## Extends
|
||||||
|
|
||||||
### Template providers [TRANSLATE]
|
### Template providers
|
||||||
|
|
||||||
Бывает так что шаблны не хранятся на файловой сиситеме, а хранятся в некотором хранилище, например, в базе данных MySQL.
|
Бывает так что шаблны не хранятся на файловой сиситеме, а хранятся в некотором хранилище, например, в базе данных MySQL.
|
||||||
В этом случае шаблонизатору нужно описать как забирать шаблоны из хранилища, как проверять дату изменения шаблона и где хранить кеш шаблонов (опционально).
|
В этом случае шаблонизатору нужно описать как забирать шаблоны из хранилища, как проверять дату изменения шаблона и где хранить кеш шаблонов (опционально).
|
||||||
Эту задачу берут на себя Providers, это объекты реальзующие интерфейс `Fenom\ProviderInterface`.
|
Эту задачу берут на себя Providers, это объекты реальзующие интерфейс `Fenom\ProviderInterface`.
|
||||||
|
|
||||||
### Cache providers [TRANSLATE]
|
|
||||||
|
|
||||||
Изначально 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");`
|
|
||||||
|
|
||||||
### Callbacks and filters
|
### Callbacks and filters
|
||||||
|
|
||||||
#### Before compile callback
|
#### Before compile callback
|
||||||
|
@ -3,4 +3,10 @@ Develop
|
|||||||
|
|
||||||
If you want to discuss the enhancement of the Fenom, create an issue on Github or submit a pull request.
|
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)
|
For questions: a.cobest@gmail.com (English, Russian languages)
|
||||||
|
|
||||||
|
|
||||||
|
* the [scheme of work](schema.md)
|
||||||
|
163
docs/ext/extend.md
Normal file
163
docs/ext/extend.md
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
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");`
|
9
docs/helpme.md
Normal file
9
docs/helpme.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Требуется помощь в переводе документации
|
||||||
|
========================================
|
||||||
|
|
||||||
|
Принимаю любую помощь в переводе статей документации. Вносить правки в документацию можете любым удобным способом:
|
||||||
|
|
||||||
|
* Сделать merge request (нажав `Edit` вверху файла)
|
||||||
|
* Прислать адрес статьи и что на что заменить. В письме лучше укажите `Fenom docs`.
|
||||||
|
|
||||||
|
Заранее благодарен!
|
@ -85,7 +85,7 @@ Operators
|
|||||||
|
|
||||||
* `$a ~ $b` - return concatenation of variables `$a` and `$b`
|
* `$a ~ $b` - return concatenation of variables `$a` and `$b`
|
||||||
|
|
||||||
### Ternary operator
|
### Ternary operators
|
||||||
|
|
||||||
* `$a ? $b : $c` - returns `$b` if `$a` is not empty, and `$c` otherwise
|
* `$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 ! $b : $c` - returns `$b` if `$a` is set, and `$c` otherwise
|
||||||
@ -99,7 +99,7 @@ Operators
|
|||||||
{$a ? 5 : 10} {* outputs 10 *}
|
{$a ? 5 : 10} {* outputs 10 *}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Check operator
|
### Check operators
|
||||||
|
|
||||||
* `$a?` - returns `TRUE` if `$a` is not empty
|
* `$a?` - returns `TRUE` if `$a` is not empty
|
||||||
* `$a!` - returns `TRUE` if `$a` is set
|
* `$a!` - returns `TRUE` if `$a` is set
|
||||||
|
@ -9,32 +9,12 @@ Documentation
|
|||||||
* [Usage](./start.md#install-fenom)
|
* [Usage](./start.md#install-fenom)
|
||||||
* [Framework adapters](./adapters.md)
|
* [Framework adapters](./adapters.md)
|
||||||
* [For developers](./dev/readme.md)
|
* [For developers](./dev/readme.md)
|
||||||
* [Configuration](./settings.md)
|
* [Configuration](./configuration.md)
|
||||||
* [Syntax](./syntax.md)
|
* [Syntax](./syntax.md)
|
||||||
* [Operators](./operators.md)
|
* [Operators](./operators.md)
|
||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
### 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
|
|
||||||
* 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/mods.md) yours
|
|
||||||
|
|
||||||
***
|
|
||||||
|
|
||||||
### Tags
|
### Tags
|
||||||
|
|
||||||
[Usage](./syntax.md#tags)
|
[Usage](./syntax.md#tags)
|
||||||
@ -52,13 +32,47 @@ Documentation
|
|||||||
* [macro](./tags/macro.md) and `import` — template functions
|
* [macro](./tags/macro.md) and `import` — template functions
|
||||||
* [autoescape](./tags/autoescape.md) — escape template fragment
|
* [autoescape](./tags/autoescape.md) — escape template fragment
|
||||||
* [raw](./tags/raw.md) — unescape template fragment
|
* [raw](./tags/raw.md) — unescape template fragment
|
||||||
* or [add](./ext/tags.md) yours
|
* 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
|
||||||
|
* 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
|
### Extends
|
||||||
|
|
||||||
* [Extensions](./ext/extensions.md)
|
* [Extend Fenom](./ext/extend.md)
|
||||||
* [Add tags](./ext/tags.md)
|
* [Add-ons](./ext/extensions.md)
|
||||||
* [Add modifiers](./ext/mods.md)
|
|
||||||
* [Parsing](./ext/parsing.md)
|
|
||||||
|
@ -32,7 +32,7 @@ Example outputs next HTML code:
|
|||||||
```
|
```
|
||||||
`{$user.id}` and `{$user['id']}` are same:
|
`{$user.id}` and `{$user['id']}` are same:
|
||||||
```smarty
|
```smarty
|
||||||
<div class="user">Hello, <a href="/users/{$user['id']}">{$user.['name']}</a>.</div>
|
<div class="user">Hello, <a href="/users/{$user['id']}">{$user['name']}</a>.</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
В случае объекта, доступ к его свойствам осущесвляется так как и в PHP — через оператор `->`:
|
В случае объекта, доступ к его свойствам осущесвляется так как и в PHP — через оператор `->`:
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
Tag {ignore} [RU]
|
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.
|
||||||
|
|
||||||
```smarty
|
```smarty
|
||||||
{ignore}
|
{ignore}
|
||||||
@ -9,7 +11,9 @@ Tag {ignore} [RU]
|
|||||||
{/ignore}
|
{/ignore}
|
||||||
```
|
```
|
||||||
|
|
||||||
You may ignore delimiters without tag `{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
|
```smarty
|
||||||
var data = { "time": obj.ts };
|
var data = { "time": obj.ts };
|
||||||
```
|
```
|
@ -1,5 +1,5 @@
|
|||||||
Tag {include} [RU]
|
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.
|
`{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.
|
||||||
|
|
||||||
@ -7,20 +7,21 @@ Tag {include} [RU]
|
|||||||
{include "about.tpl"}
|
{include "about.tpl"}
|
||||||
```
|
```
|
||||||
|
|
||||||
Переменные для подключаемого шаблона можно переопределить, задавая их аргументами тега.
|
If you need to set yours variables for template list them in attributes.
|
||||||
|
|
||||||
```smarty
|
```smarty
|
||||||
{include "about.tpl" page=$item limit=50}
|
{include "about.tpl" page=$item limit=50}
|
||||||
```
|
```
|
||||||
|
|
||||||
Все изменения переменных в подключаемом шаблоне не будут воздействовать на родительский шаблон.
|
All variables changed in child template has no affect to variables in parent template.
|
||||||
|
|
||||||
### {insert}
|
### {insert}
|
||||||
|
|
||||||
The tag insert template code instead self.
|
The tag insert template code instead self.
|
||||||
|
|
||||||
* No dynamic name allowed
|
* No dynamic name allowed.
|
||||||
* No variables as attribute allowed
|
* No variables as attribute allowed.
|
||||||
|
* Increase performance because insert code as is in compilation time.
|
||||||
|
|
||||||
For example, main.tpl:
|
For example, main.tpl:
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ b.tpl:
|
|||||||
b: {$b}
|
b: {$b}
|
||||||
```
|
```
|
||||||
|
|
||||||
Во время разбора шаблона код шаблона `b.tpl` будет вставлен в код шаблона `main.tpl` как есть:
|
Code of `b.tpl` will be inserted into `main.tpl` as is:
|
||||||
|
|
||||||
```smarty
|
```smarty
|
||||||
a: {$a}
|
a: {$a}
|
||||||
|
@ -15,11 +15,5 @@ namespace {
|
|||||||
|
|
||||||
$fenom = Fenom::factory(__DIR__.'/templates', __DIR__.'/compiled', Fenom::FORCE_COMPILE);
|
$fenom = Fenom::factory(__DIR__.'/templates', __DIR__.'/compiled', Fenom::FORCE_COMPILE);
|
||||||
|
|
||||||
$fenom->display("extends/75-child.tpl", array(
|
var_dump($fenom->compile("concat-bug.tpl", false)->getBody());
|
||||||
"user" => array(
|
|
||||||
"name" => "Ivka",
|
|
||||||
'type' => 'new'
|
|
||||||
),
|
|
||||||
'type' => 'new'
|
|
||||||
));
|
|
||||||
}
|
}
|
2
sandbox/templates/concat-bug.tpl
Normal file
2
sandbox/templates/concat-bug.tpl
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Some eval:
|
||||||
|
{$dop_content = ": some texta"}
|
@ -323,7 +323,7 @@ class Fenom
|
|||||||
*
|
*
|
||||||
* @param string|Fenom\ProviderInterface $source path to templates or custom provider
|
* @param string|Fenom\ProviderInterface $source path to templates or custom provider
|
||||||
* @param string $compile_dir path to compiled files
|
* @param string $compile_dir path to compiled files
|
||||||
* @param int $options
|
* @param int|array $options
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
* @return Fenom
|
* @return Fenom
|
||||||
*/
|
*/
|
||||||
|
@ -147,7 +147,6 @@ class Provider implements ProviderInterface
|
|||||||
public function templateExists($tpl)
|
public function templateExists($tpl)
|
||||||
{
|
{
|
||||||
return ($path = realpath($this->_path . "/" . $tpl)) && strpos($path, $this->_path) === 0;
|
return ($path = realpath($this->_path . "/" . $tpl)) && strpos($path, $this->_path) === 0;
|
||||||
// return file_exists($this->_path . "/" . $tpl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -379,6 +379,9 @@ class Template extends Render
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $tag_name
|
||||||
|
*/
|
||||||
public function ignore($tag_name) {
|
public function ignore($tag_name) {
|
||||||
$this->_ignore = $tag_name;
|
$this->_ignore = $tag_name;
|
||||||
}
|
}
|
||||||
@ -724,16 +727,24 @@ class Template extends Render
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} elseif ($tokens->is('~')) { // string concatenation operator: 'asd' ~ $var
|
} elseif ($tokens->is('~')) { // string concatenation operator: 'asd' ~ $var
|
||||||
$concat = array(array_pop($exp));
|
if($tokens->isNext('=')) { // ~=
|
||||||
while ($tokens->is('~')) {
|
$exp[] = ".=";
|
||||||
$tokens->next();
|
$tokens->next()->next();
|
||||||
if ($tokens->is(T_LNUMBER, T_DNUMBER)) {
|
} else {
|
||||||
$concat[] = "strval(" . $this->parseTerm($tokens) . ")";
|
$concat = array(array_pop($exp));
|
||||||
} else {
|
|
||||||
$concat[] = $this->parseTerm($tokens);
|
while ($tokens->is('~')) {
|
||||||
|
$tokens->next();
|
||||||
|
if ($tokens->is(T_LNUMBER, T_DNUMBER)) {
|
||||||
|
$concat[] = "strval(" . $this->parseTerm($tokens) . ")";
|
||||||
|
} else {
|
||||||
|
if(!$concat[] = $this->parseTerm($tokens)) {
|
||||||
|
throw new UnexpectedTokenException($tokens);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
$exp[] = "(" . implode(".", $concat) . ")";
|
||||||
}
|
}
|
||||||
$exp[] = "(" . implode(".", $concat) . ")";
|
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1294,7 +1305,7 @@ class Template extends Render
|
|||||||
$_arr .= $this->parseArray($tokens);
|
$_arr .= $this->parseArray($tokens);
|
||||||
$key = false;
|
$key = false;
|
||||||
$val = true;
|
$val = true;
|
||||||
} elseif ($tokens->is(']') && !$key) {
|
} elseif ($tokens->is(']') && (!$key || $tokens->prev[0] === ',')) {
|
||||||
$tokens->next();
|
$tokens->next();
|
||||||
return $_arr . ')';
|
return $_arr . ')';
|
||||||
} else {
|
} else {
|
||||||
|
@ -1170,6 +1170,7 @@ class TemplateTest extends TestCase
|
|||||||
array('{"string" ~ ++$one ~ "end"}', "string2end"),
|
array('{"string" ~ ++$one ~ "end"}', "string2end"),
|
||||||
array('{"string" ~ "one" ~ "end"}', "stringoneend"),
|
array('{"string" ~ "one" ~ "end"}', "stringoneend"),
|
||||||
array('{"string" ~ 1 ~ "end"}', "string1end"),
|
array('{"string" ~ 1 ~ "end"}', "string1end"),
|
||||||
|
array('{$one ~= "string"} is {$one}', "1string is 1string"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1539,6 +1540,7 @@ class TemplateTest extends TestCase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerConcat
|
* @dataProvider providerConcat
|
||||||
|
* @group testConcat
|
||||||
*/
|
*/
|
||||||
public function testConcat($code, $result)
|
public function testConcat($code, $result)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user