Fix switch. Update docs

This commit is contained in:
bzick 2014-05-14 17:07:48 +04:00
parent d8c4ea6994
commit c5f644c3db
9 changed files with 176 additions and 147 deletions

View File

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

94
docs/configuration.md Normal file
View File

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

View File

@ -1,19 +0,0 @@
Installation
============
For installation use [composer](http://getcomposer.org). Add in your `composer.json` requirements:
```json
{
"require": {
"fenom/fenom": "2.*"
}
}
```
or use shell
`composer require fenom/fenom`
If you do not use composer - use `psr-0` format for loading Fenom's classes or just register Fenom's autoloader:
```php
Fenom::registerAutoload();
```

View File

@ -1,14 +1,15 @@
Documentation
=============
**Please, help translate documentation to english or fix typos. [Read more](./helpme.md).**
### Fenom
* [Install](./install.md)
* [Usage](./usage.md)
* [Fenom adapters](./adapters.md)
* [Develop](./dev/readme.md)
* [Settings](./settings.md)
* [Callbacks and filters](./callbacks.md)
* [Quick start](./start.md)
* [Usage](./start.md#install-fenom)
* [Framework adapters](./adapters.md)
* [For developers](./dev/readme.md)
* [Configuration](./settings.md)
* [Syntax](./syntax.md)
* [Operators](./operators.md)
@ -18,16 +19,16 @@ Documentation
[Usage](./syntax.md#modifiers)
* [upper](./mods/upper.md) aka `up`
* [lower](./mods/lower.md) aka `low`
* [date_format](./mods/date_format.md)
* [date](./mods/date.md)
* [truncate](./mods/truncate.md)
* [escape](./mods/escape.md) aka `e`
* [unescape](./mods/unescape.md)
* [strip](./mods/strip.md)
* [length](./mods/length.md)
* [in](./mods/in.md)
* [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
@ -38,19 +39,19 @@ Documentation
[Usage](./syntax.md#tags)
* [var](./tags/var.md)
* [if](./tags/if.md), `elseif` and `else`
* [foreach](./tags/foreach.md), `foreaelse`, `break` and `continue`
* [for](./tags/for.md), `forelse`, `break` and `continue`
* [switch](./tags/switch.md), `case`, `default`
* [cycle](./tags/cycle.md)
* [include](./tags/include.md), `insert`
* [extends](./tags/extends.md), `use`, `block` and `parent`
* [filter](./tags/filter.md)
* [ignore](./tags/ignore.md)
* [macro](./tags/macro.md) and `import`
* [autoescape](./tags/autoescape.md)
* [raw](./tags/raw.md)
* [var](./tags/var.md) — define variable
* [if](./tags/if.md), `elseif` and `else` — conditional statement
* [foreach](./tags/foreach.md), `foreaelse`, `break` and `continue` — traversing items in an array or object
* [for](./tags/for.md), `forelse`, `break` and `continue` — loop statement
* [switch](./tags/switch.md), `case`, `default`
* [cycle](./tags/cycle.md) — cycles on an array of values
* [include](./tags/include.md), `insert` — includes and evaluates the specified template
* [extends](./tags/extends.md), `use`, `block` and `parent` — template inheritance
* [filter](./tags/filter.md) — apply modifier on a block of template data
* [ignore](./tags/ignore.md) — ignore Fenom syntax
* [macro](./tags/macro.md) and `import` — template functions
* [autoescape](./tags/autoescape.md) — escape template fragment
* [raw](./tags/raw.md) — unescape template fragment
* or [add](./ext/tags.md) yours
***
@ -59,6 +60,5 @@ Documentation
* [Extensions](./ext/extensions.md)
* [Add tags](./ext/tags.md)
* [Add modificators](./ext/mods.md)
* [Add template provider](./ext/provider.md)
* [Add modifiers](./ext/mods.md)
* [Parsing](./ext/parsing.md)

View File

@ -1,46 +0,0 @@
Settings
========
### Template cache
```php
$fenom->setCompileDir($dir);
```
This method set the name of the directory where template caches are stored. By default this is `/tmp`. This directory must be writeable.
### Template settings
```php
// set options using factory
$fenom = Fenom::factory($tpl_dir, $compile_dir, $options);
// or inline using method setOptions
$fenom->setOptions($options);
```
Options may by associative array like `'option_name' => true` or bitwise mask.
| Code | Constant | Description | Affect |
| ---------------------- | ------------------------- | ------------ | ------- |
| *disable_methods* | `Fenom::DENY_METHODS` | disable calling methods of objects in templates. | |
| *disable_native_funcs* | `Fenom::DENY_INLINE_FUNCS`| disable calling native function in templates, except allowed. | |
| *auto_reload* | `Fenom::AUTO_RELOAD` | reload template if source will be changed | decreases performance |
| *force_compile* | `Fenom::FORCE_COMPILE` | recompile template every time when the template renders | greatly decreases performance |
| *disable_cache* | `Fenom::DISABLE_CACHE` | disable compile cache | greatly decreases performance |
| *force_include* | `Fenom::FORCE_INCLUDE` | paste template body instead of include-tag | increases performance, increases cache size |
| *auto_escape* | `Fenom::AUTO_ESCAPE` | html-escape each variables outputs | decreases performance |
| *force_verify* | `Fenom::FORCE_VERIFY` | check existence every used variable | decreases performance |
| *auto_trim* | `Fenom::AUTO_TRIM` | remove space-characters before and after tags | |
| *disable_statics* | `Fenom::DENY_STATICS` | disable calling static methods in templates. | |
```php
$fenom->setOptions(array(
"compile_check" => true,
"force_include" => true
));
// same
$fenom->setOptions(Fenom::AUTO_RELOAD | Fenom::FORCE_INCLUDE);
```
**By default all options disabled**

View File

@ -5,7 +5,7 @@ Fenom implements [Smarty](http://www.smarty.net/) syntax with some improvements.
All Fenom tags enclosed in the delimiters `{` and `}`, for example `{var $five = 5}`.
If you wanna leave delimiters as is in the template use [special statements or tags](#ignoring-delimiters).
*Note*
**Note**
Fenom implements [Smarty](http://www.smarty.net/) syntax but not implements Smarty tags, however, some tags very similar.
But not so bad, Fenom has the [extras](https://github.com/bzick/fenom-extra) that make Fenom like Smarty.
@ -14,7 +14,7 @@ But not so bad, Fenom has the [extras](https://github.com/bzick/fenom-extra) tha
Variables in Fenom can be either displayed directly or used as arguments for functions, attributes and modifiers,
inside conditional expressions, etc.
### Example variables
### Use variables
Next example uses simple variables `$user_id` ans `$user_name`
```smarty
@ -30,38 +30,37 @@ Example outputs next HTML code:
```smarty
<div class="user">Hello, <a href="/users/{$user.id}">{$user.name}</a>.</div>
```
`{$user.id}` and `{$user['id']}` are same:
```smarty
<div class="user">Hello, <a href="/users/{$user['id']}">{$user.['name']}</a>.</div>
```
`{$user.id}` and `{$user['id']}` are same.
В случае объекта, доступ к его свойствам осущесвляется так как и в PHP — через оператор `->`:
```smarty
<div class="user">Hello, <a href="/users/{$user->id}">{$user->name}</a>.</div>
```
Методы, как и свойства можно вызвать через оператор `->`, передав в метод любые рагументы:
```smarty
<div class="user">Hello, <a href="/users/{$user->getId()}">{$user->getName()}</a>.</div>
```
*Note*
Be careful, Fenom do not checks existence of the method before invoke.
To avoid the problem class of the object have to define method `__call`, which throws an exception etc.
Also you may disable invoke method in [settings](./docs/settings.md).
To avoid the problem class of the object have to define method `__call`, which throws an exception, etc.
Also you can prohibit method call in [settings](./docs/configuration.md).
Multidimensional value support
Можно комбинировать различные варианты вызовов:
```smarty
{$foo.bar.baz}
{$foo.$bar.$baz}
{$foo[4].baz}
{$foo[4].$baz}
{$foo[5].baz}
{$foo[5].$baz}
{$foo.bar.baz[4]}
{$foo[ $bar.baz ]}
```
```smarty
{$foo}
{$bar}
{$foo[4]}
{$foo.4}
{$foo[5]}
{$foo.5}
{$foo.bar}
{$foo.'bar'}
{$foo."bar"}
@ -71,6 +70,8 @@ Multidimensional value support
{$foo[$bar]}
{$foo->bar}
{$foo->bar.buz}
{$foo->bar.buz[ $bar->getId("user") ]}
{$foo->bar(5)->buz(5.5)}
```
### System variable
@ -107,16 +108,6 @@ Unnamed system variable starts with `$.` and allows access to global variables a
See all [operators](./operators.md)
### Object support
```smarty
{$object->item}
{$object->item|upper} {* apply modifier *}
{$object->item->method($y, 'named')}
{$object->item->method($y->name, 'named')|upper} {* apply modifier to method result*}
```
You may disable call methods in template, see in [security options](./settings.md) option `deny_method`
### Static method support
@ -196,7 +187,7 @@ but if use single quote any template expressions will be on display as it is
{'Hi, {$user.name|up}'} outputs "Hi, {$user.name|up}"
```
## Numbers
### Numbers
```smarty
{2|pow:10}
@ -205,7 +196,7 @@ but if use single quote any template expressions will be on display as it is
{1e-6|round}
```
### Modifiers
## 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.
@ -224,7 +215,7 @@ but if use single quote any template expressions will be on display as it is
[List of modifiers](./main.md#modifiers)
### Tags
## Tags
Basically, tag seems like
@ -273,12 +264,13 @@ Tags starts with name and may have attributes
### Ignoring template code
В шаблонизаторе Fenom используются фигурные скобки для отделения HTML от кода Fenom.
Если требуется вывести текст, содержащий фигурные скобки, помните о следующих возможностях:
Если требуется вывести текст, содержащий фигурные скобки, то есть следующие варианты это сделать:
1. Использование блочного тега `{ignore}{/ignore}`. Текст внутри этого тега текст не компилируется шаблонизатором и выводится как есть.
2. Если после открывающей фигурной скобки есть пробельный символ (пробел или `\t`) или перенос строки (`\r` или `\n`), то она не воспринимается как разделитель кода Fenom и код после неё выводится как есть.
3. Установить опцию `:ignore` у блочного тега. Все Fenom теги внутри блока будут проигнорированны
Пример:
Example:
```smarty
{ignore}
@ -292,10 +284,10 @@ Tags starts with name and may have attributes
e.innerHTML = text;
document.body.appendChild(e);
})('test');
</script>
{if:ignore $js_enabled}
{if:ignore $cdn.yandex}
var item = {cdn: "//yandex.st/"};
{/if}
</script>
```
Outputs
@ -310,6 +302,7 @@ Outputs
e.innerHTML = text;
document.body.appendChild(e);
})('test');
var item = {cdn: "//yandex.st/"};
</script>
```
@ -341,10 +334,7 @@ Outputs
| name | code | type | description |
| ------- | ---- | ----- | ------------ |
| strip | s | block | remove any multi-whitespaces |
| ltrim | l | any | remove spaces left of the tag |
| rtrim | r | any | remove spaces right of the tag |
| trim | t | any | remove spaces near tag |
| 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 |

View File

@ -15,7 +15,7 @@ Tag `{switch}` accepts any expression. But `{case}` accepts only static scalar v
...
{case <value3>}
...
{default case <value1>}
{case default, <value1>}
...
{/switch}
```
@ -32,7 +32,7 @@ For example,
It is current item
{case 'new', 'newer'}
It is new item, again
{default}
{case default}
I don't know the type {$type}
{/switch}
```

View File

@ -366,10 +366,10 @@ class Compiler
private static function _caseResort(Tag $scope)
{
$content = $scope->cutContent();
if ($scope["last"] === false) {
foreach ($scope["last"] as $case) {
if($case === false) {
$scope["default"] .= $content;
} else {
foreach ($scope["last"] as $case) {
if (!isset($scope["case"][$case])) {
$scope["case"][$case] = "";
}
@ -384,14 +384,19 @@ class Compiler
*
* @static
* @param Tokenizer $tokens
* @param Tag $scope
* @param Tag $tag
* @return string
*/
public static function tagCase(Tokenizer $tokens, Tag $scope)
public static function tagCase(Tokenizer $tokens, Tag $tag)
{
self::_caseResort($scope);
self::_caseResort($tag);
do {
$scope["last"][] = $scope->tpl->parseScalar($tokens, false);
if($tokens->is(T_DEFAULT)) {
$tag["last"][] = false;
$tokens->next();
} else {
$tag["last"][] = $tag->tpl->parseScalar($tokens, false);
}
if ($tokens->is(',')) {
$tokens->next();
} else {
@ -413,7 +418,7 @@ class Compiler
public static function tagDefault($tokens, Tag $scope)
{
self::_caseResort($scope);
$scope["last"] = false;
$scope["last"][] = false;
return '';
}

View File

@ -861,7 +861,7 @@ class TemplateTest extends TestCase
$code1 = 'Switch: {switch $a}
{case 1, "one"} one
{case 2, "two"} two
{case "string"} str
{case "string", default} str
{default} def
{/switch} end';
@ -881,6 +881,7 @@ class TemplateTest extends TestCase
array($code1, array("a" => 2), 'Switch: two end'),
array($code1, array("a" => 'two'), 'Switch: two end'),
array($code1, array("a" => "string"), 'Switch: str end'),
array($code1, array("a" => "unk"), 'Switch: str def end'),
array($code2, array("a" => "unk"), 'Switch: end'),
array($code3, array("a" => 1), 'Switch: one end'),
array($code3, array("a" => 'one'), 'Switch: one end'),