mirror of
https://github.com/fenom-template/fenom.git
synced 2023-08-10 21:13:07 +03:00
commit
964f20a914
10
.gitignore
vendored
10
.gitignore
vendored
@ -1,17 +1,9 @@
|
||||
.idea
|
||||
vendor
|
||||
coverage
|
||||
build
|
||||
composer.lock
|
||||
composer.phar
|
||||
tests/resources/compile/*
|
||||
!.gitkeep
|
||||
tests/resources/template/*
|
||||
!.gitkeep
|
||||
sandbox/compiled/*
|
||||
!.gitkeep
|
||||
benchmark/compile/*
|
||||
benchmark/templates/inheritance/smarty
|
||||
benchmark/templates/inheritance/twig
|
||||
benchmark/sandbox/compiled/*
|
||||
!.gitkeep
|
||||
sandbox/compiled/*
|
18
CHANGELOG.md
18
CHANGELOG.md
@ -1,6 +1,24 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
## 2.4.0 (2015-01-02)
|
||||
|
||||
- Fix bugs #120, #104, #119
|
||||
- Add `~~` operator. Concatenation with space.
|
||||
- Improve #126. Disable clearcachestats() by default in Fenom\Provider. clearcachestats() may be enabled.
|
||||
- Improve accessors (unnamed system variable). Now possible add, redefine yours accessors.
|
||||
- ++Docs
|
||||
- ++Tests
|
||||
|
||||
### 2.3.1 (2014-11-06)
|
||||
|
||||
- Fix #122
|
||||
|
||||
### 2.3.1 (2014-08-27)
|
||||
|
||||
- Fix #105
|
||||
- ++Tests
|
||||
|
||||
## 2.3.0 (2014-08-08)
|
||||
|
||||
- Add tags {set} and {add}
|
||||
|
@ -1,8 +1,6 @@
|
||||
Documentation
|
||||
=============
|
||||
|
||||
**Please, help translate documentation to english or fix typos. [Read more](./helpme.md).**
|
||||
|
||||
### Fenom
|
||||
|
||||
* [Quick start](./start.md)
|
||||
@ -11,7 +9,13 @@ Documentation
|
||||
* [For developers](./dev/readme.md)
|
||||
* [Configuration](./configuration.md)
|
||||
* [Syntax](./syntax.md)
|
||||
* [Operators](./operators.md)
|
||||
* [Variables](./syntax.md#Variables)
|
||||
* [Values](./syntax.md#Values)
|
||||
* [Arrays](./syntax.md#Arrays)
|
||||
* [Operators](./operators.md)
|
||||
* [Modificators](./syntax.md#Modificators)
|
||||
* [Tags](./syntax.md#Tags)
|
||||
* [Tag configuration](./syntax.md#Tag-configuration)
|
||||
|
||||
***
|
||||
|
||||
@ -19,7 +23,7 @@ Documentation
|
||||
|
||||
[Usage](./syntax.md#tags)
|
||||
|
||||
* [var](./tags/var.md) — define variable
|
||||
* [set](./tags/var.md), `add` and `var` — define variables
|
||||
* [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
|
||||
@ -72,7 +76,7 @@ Documentation
|
||||
* [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`
|
||||
* [String concatenation operators](./operators.md#string-operators) — `$str1 ~ $str2`, `$str1 ~~ $str2`, `$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`
|
||||
|
@ -76,16 +76,16 @@ Below is complex example:
|
||||
|
||||
### System variable
|
||||
|
||||
Unnamed system variable starts with `$.` and allows access to global variables and template information:
|
||||
Unnamed system variable starts with `$.` and allows access to global system variables and template information:
|
||||
|
||||
* `$.get` is `$_GET`.
|
||||
* `$.post` is `$_POST`.
|
||||
* `$.cookie` is `$_COOKIE`.
|
||||
* `$.session` is `$_SESSION`.
|
||||
* `$.globals` is `$GLOBALS`.
|
||||
* `$.request` is `$_REQUEST`.
|
||||
* `$.files` is `$_FILES`.
|
||||
* `$.server` is `$_SERVER`.
|
||||
* `$.get` — array `$_GET`.
|
||||
* `$.post` — array `$_POST`.
|
||||
* `$.cookie` — array `$_COOKIE`.
|
||||
* `$.session` — array `$_SESSION`.
|
||||
* `$.globals` — array `$GLOBALS`.
|
||||
* `$.request` — array `$_REQUEST`.
|
||||
* `$.files` — array `$_FILES`.
|
||||
* `$.server` — array `$_SERVER`.
|
||||
* `$.env` is `$_ENV`.
|
||||
* `$.tpl.name` returns current template name.
|
||||
* `$.tpl.schema` returns current schema of the template.
|
||||
@ -98,6 +98,165 @@ Unnamed system variable starts with `$.` and allows access to global variables a
|
||||
{/if}
|
||||
```
|
||||
|
||||
|
||||
Безименная системная переменная начинается с `$.` и предоставляет доступ к глобальным системным переменным и системной информации:
|
||||
|
||||
* `$.env` — array `$_ENV`.
|
||||
* `$.get` — array `$_GET`.
|
||||
* `$.post` — array `$_POST`.
|
||||
* `$.files` — array `$_FILES`.
|
||||
* `$.cookie` — array `$_COOKIE`.
|
||||
* `$.server` — array `$_SERVER`.
|
||||
* `$.session` — array `$_SESSION`.
|
||||
* `$.globals` — array `$GLOBALS`.
|
||||
* `$.request` — array `$_REQUEST`.
|
||||
* `$.tpl.name` returns name for current template.
|
||||
* `$.tpl.basename` returns name without schema for current template.
|
||||
* `$.tpl.scm` returns schema for current template.
|
||||
* `$.tpl.options` returns options as integer for current template.
|
||||
* `$.tpl.depends` <!-- возвращает массив шаблонов на которые ссылается текущий шаблон.-->
|
||||
* `$.tpl.time` returns last modified timestamp for current template
|
||||
* `$.version` returns Fenom version.
|
||||
* `$.const` returns the value of a PHP constant: `$.const.PHP_EOL` get value of constant `PHP_EOL`.
|
||||
Supported namespace for constants, use dot instead of back-slash for namespace separators: `$.const.Storage.FS::DIR_SEPARATOR` get value of constant `Storage\FS::DIR_SEPARATOR`.
|
||||
But if constant `Storage\FS::DIR_SEPARATOR` does not exists then constant `Storage\FS\DIR_SEPARATOR` will be taken.
|
||||
* `$.php`call PHP static method. `$.php.Storage.FS::put($filename, $data)` calls method `Storage\FS::put($filename, $data)`.
|
||||
`$.php.Storage.FS.put($filename, $data)` `Storage\FS\put($filename, $data)`
|
||||
* System function `$.fetch($name, $values)` calls Fenom::fetch() in template. `$name` — template name,
|
||||
`$values` — additional variables.
|
||||
* also you may [add](./ext/extend.md#Extends-system-variable) yours system variables and functions.
|
||||
|
||||
|
||||
## Scalar values
|
||||
|
||||
### Strings
|
||||
|
||||
A string literal can be specified in two different ways: double quotes (`"string"`) and single quotes (`'string'`).
|
||||
|
||||
#### Double quotes
|
||||
|
||||
If the string is enclosed in double-quotes `"`, Fenom will interpret more escape sequences for special characters:
|
||||
|
||||
|
||||
| Последовательность | Значение |
|
||||
|---------------------|----------|
|
||||
| `\n` | linefeed (LF or 0x0A (10) in ASCII)
|
||||
| `\r` | carriage return (CR or 0x0D (13) in ASCII)
|
||||
| `\t` | horizontal tab (HT or 0x09 (9) in ASCII)
|
||||
| `\v` | vertical tab (VT or 0x0B (11) in ASCII)
|
||||
| `\f` | form feed (FF or 0x0C (12) in ASCII)
|
||||
| `\\` | backslash
|
||||
| `\$` | dollar sign
|
||||
| `\"` | double-quote
|
||||
| `\[0-7]{1,3}` | the sequence of characters matching the regular expression is a character in octal notation
|
||||
| `\x[0-9A-Fa-f]{1,2}`| the sequence of characters matching the regular expression is a character in hexadecimal notation
|
||||
|
||||
The most important feature of double-quoted strings is the fact that variable names will be expanded.
|
||||
There are two types of syntax: a simple one and a complex one. The simple syntax is the most common and convenient.
|
||||
It provides a way to embed a variable, an array value, or an object property in a string with a minimum of effort.
|
||||
The complex syntax can be recognised by the curly braces surrounding the expression.
|
||||
|
||||
##### Simple syntax
|
||||
|
||||
If a dollar sign `$` is encountered, the parser will greedily take as many tokens as possible to form a valid variable name.
|
||||
Enclose the variable name in curly braces to explicitly specify the end of the name.
|
||||
|
||||
```smarty
|
||||
{"Hi, $username!"} outputs "Hi, Username!"
|
||||
```
|
||||
|
||||
For anything more complex, you should use the complex syntax.
|
||||
|
||||
##### Complex syntax
|
||||
|
||||
This isn't called complex because the syntax is complex, but because it allows for the use of complex expressions.
|
||||
Any scalar variable, array element or object property with a string representation can be included via this syntax.
|
||||
Simply write the expression the same way as it would appear outside the string, and then wrap it in `{` and `}`.
|
||||
Since `{` can not be escaped, this syntax will only be recognised when the `$` immediately follows the `{`.
|
||||
Use `{\$` to get a literal `{$`. Some examples to make it clear:
|
||||
|
||||
|
||||
```smarty
|
||||
{"Hi, {$user.name}!"} outputs: Hi, Username!
|
||||
{"Hi, {$user->name}!"} outputs: Hi, Username!
|
||||
{"Hi, {$user->getName()}!"} outputs: Hi, Username!
|
||||
{"Hi, {\$user->name}!"} outputs: Hi, {\$user->name}!
|
||||
```
|
||||
|
||||
Allows modifiers and operators:
|
||||
|
||||
```smarty
|
||||
{"Hi, {$user.name|up}!"} outputs: Hi, USERNAME!
|
||||
{"Hi, {$user.name|up ~ " (admin)"}!"} outputs: Hi, USERNAME (admin)!
|
||||
```
|
||||
|
||||
#### Single quotes
|
||||
|
||||
The simplest way to specify a string is to enclose it in single quotes (the character `'`).
|
||||
To specify a literal single quote, escape it with a backslash (`\`).
|
||||
To specify a literal backslash, double it (`\\`).
|
||||
All other instances of backslash will be treated as a literal backslash: this means that the other escape sequences you might be used to, such as `\r` or `\n`, will be output literally as specified rather than having any special meaning.
|
||||
|
||||
```smarty
|
||||
{'Hi, $foo'} outputs: 'Hi, $foo'
|
||||
{'Hi, {$foo}'} outputs: 'Hi, {$foo}'
|
||||
{'Hi, {$user.name}'} outputs: 'Hi, {$user.name}'
|
||||
{'Hi, {$user.name|up}'} outputs: "Hi, {$user.name|up}"
|
||||
```
|
||||
|
||||
### Integers
|
||||
|
||||
Integers can be specified in decimal (base 10), hexadecimal (base 16), octal (base 8) or binary (base 2) notation, optionally preceded by a sign (- or +).
|
||||
|
||||
To use octal notation, precede the number with a 0 (zero).
|
||||
To use hexadecimal notation precede the number with 0x.
|
||||
To use binary notation precede the number with 0b.
|
||||
|
||||
``smarty
|
||||
{var $a = 1234} decimal number
|
||||
{var $a = -123} a negative number
|
||||
{var $a = 0123} octal number (equivalent to 83 decimal)
|
||||
{var $a = 0x1A} hexadecimal number (equivalent to 26 decimal)
|
||||
{var $a = 0b11111111} binary number (equivalent to 255 decimal)
|
||||
```
|
||||
|
||||
**Notice**
|
||||
Binary notation (`0b1011011`) unavailable on PHP older than 5.3.
|
||||
|
||||
**Notice**
|
||||
The size of an integer is platform-dependent, although a maximum value of about two billion is the usual value (that's 32 bits signed).
|
||||
64-bit platforms usually have a maximum value of about 9E18
|
||||
|
||||
**Warning**
|
||||
If an invalid digit is given in an octal integer (i.e. 8 or 9), the rest of the number is ignored.
|
||||
|
||||
### Floating point numbers
|
||||
|
||||
Floating point numbers (also known as "floats", "doubles", or "real numbers") can be specified using any of the following syntaxes:
|
||||
|
||||
```smarty
|
||||
{var $a = 1.234}
|
||||
{var $b = 1.2e3}
|
||||
{var $c = 7E-10}
|
||||
```
|
||||
|
||||
### Booleans
|
||||
|
||||
This is the simplest type. A boolean expresses a truth value. It can be either TRUE or FALSE.
|
||||
To specify a boolean literal, use the constants TRUE or FALSE. Both are case-insensitive.
|
||||
|
||||
|
||||
```smarty
|
||||
{set $a = true}
|
||||
```
|
||||
|
||||
### NULL
|
||||
|
||||
The special NULL value represents a variable with no value. NULL is the only possible value of type null.
|
||||
|
||||
------
|
||||
|
||||
|
||||
### Variable operations
|
||||
|
||||
Fenom supports math, logic, comparison, containment, test, concatenation operators...
|
||||
@ -206,6 +365,97 @@ Floating point numbers (also known as "floats", "doubles", or "real numbers") ca
|
||||
{var $c = 7E-10}
|
||||
```
|
||||
|
||||
### Operators
|
||||
|
||||
Fenom supports operators on values:
|
||||
|
||||
* Arithmetic operators — `+`, `-`, `*`, `/`, `%`
|
||||
* Logical operators — `||`, `&&`, `!$var`, `and`, `or`, `xor`
|
||||
* Comparison operators — `>`, `>=`, `<`, `<=`, `==`, `!=`, `!==`, `<>`
|
||||
* Bitwise operators — `|`, `&`, `^`, `~$var`, `>>`, `<<`
|
||||
* Assignment operators — `=`, `+=`, `-=`, `*=`, `/=`, `%=`, `&=`, `|=`, `^=`, `>>=`, `<<=`
|
||||
* String concatenation operators — `$str1 ~ $str2`, `$str1 ~~ $str2`, `$str1 ~= $str2`
|
||||
* Ternary operators — `$a ? $b : $c`, `$a ! $b : $c`, `$a ?: $c`, `$a !: $c`
|
||||
* Check operators — `$var?`, `$var!`
|
||||
* Test operator — `is`, `is not`
|
||||
* Containment operator — `in`, `not in`
|
||||
|
||||
About [operators](./operators.md).
|
||||
|
||||
## Arrays
|
||||
|
||||
An array can be created using the `[]` language construct. It takes any number of comma-separated `key => value` pairs as arguments.
|
||||
```
|
||||
[
|
||||
key => value,
|
||||
key2 => value2,
|
||||
key3 => value3,
|
||||
...
|
||||
]
|
||||
```
|
||||
The comma after the last array element is optional and can be omitted.
|
||||
This is usually done for single-line arrays, i.e. `[1, 2]` is preferred over `[1, 2, ]`.
|
||||
For multi-line arrays on the other hand the trailing comma is commonly used, as it allows easier addition of new elements at the end.
|
||||
|
||||
```smarty
|
||||
{set $array = [
|
||||
"foo" => "bar",
|
||||
"bar" => "foo",
|
||||
]}
|
||||
```
|
||||
|
||||
The key can either be an integer or a string. The value can be of any type.
|
||||
|
||||
Additionally the following key casts will occur:
|
||||
|
||||
* Strings containing valid integers will be cast to the integer type. E.g. the key "8" will actually be stored under 8.
|
||||
On the other hand "08" will not be cast, as it isn't a valid decimal integer.
|
||||
* Floats are also cast to integers, which means that the fractional part will be truncated.
|
||||
E.g. the key 8.7 will actually be stored under 8.
|
||||
* Bools are cast to integers, too, i.e. the key true will actually be stored under 1 and the key false under 0.
|
||||
* Null will be cast to the empty string, i.e. the key null will actually be stored under "".
|
||||
* Arrays and objects can not be used as keys. Doing so will result in a warning: Illegal offset type.
|
||||
|
||||
If multiple elements in the array declaration use the same key, only the last one will be used as all others are overwritten.
|
||||
|
||||
An existing array can be modified by explicitly setting values in it.
|
||||
This is done by assigning values to the array, specifying the key after dot or in brackets.
|
||||
The key can also be omitted, resulting in an empty pair of brackets (`[]`).
|
||||
|
||||
```smarty
|
||||
{set $arr.key = value}
|
||||
{set $arr[] = value} {* append value to end of array *}
|
||||
```
|
||||
|
||||
If `$arr` doesn't exist yet, it will be created, so this is also an alternative way to create an array.
|
||||
This practice is however discouraged because if `$arr` already contains some value (e.g. string from request variable)
|
||||
then this value will stay in the place and `[]` may actually stand for string access operator.
|
||||
It is always better to initialize variable by a direct assignment.
|
||||
|
||||
## Constants
|
||||
|
||||
A constant is an identifier (name) for a simple value in PHP.
|
||||
As the name suggests, that value cannot change during the execution of the script.
|
||||
A constant is case-sensitive by default. By convention, constant identifiers are always uppercase.
|
||||
|
||||
## PHP functions and methods
|
||||
|
||||
**TODO**
|
||||
|
||||
```smarty
|
||||
{$.php.some_function($a, $b, $c)}
|
||||
```
|
||||
|
||||
```smarty
|
||||
{$.php.MyClass::method($a, $b, $c)}
|
||||
```
|
||||
|
||||
|
||||
```smarty
|
||||
{$.php.My.NS.some_function($a, $b, $c)}
|
||||
{$.php.My.NS.MyClass::method($a, $b, $c)}
|
||||
```
|
||||
|
||||
## Modifiers
|
||||
|
||||
|
||||
@ -229,63 +479,7 @@ These parameters follow the modifier name and are separated by a : (colon).
|
||||
|
||||
## Tags
|
||||
|
||||
Basically, tag seems like
|
||||
|
||||
```smarty
|
||||
{FUNCNAME attr1 = "val1" attr2 = $val2}
|
||||
```
|
||||
|
||||
Tags starts with name and may have attributes
|
||||
|
||||
Это общий формат функций, но могут быть исключения, например функция [{var}](./tags/var.md), использованная выше.
|
||||
|
||||
```smarty
|
||||
{include file="my.tpl"}
|
||||
{var $foo=5}
|
||||
{if $user.loggined}
|
||||
Welcome, <span style="color: red">{$user.name}!</span>
|
||||
{else}
|
||||
Who are you?
|
||||
{/if}
|
||||
```
|
||||
|
||||
В общем случае аргументы принимают любой формат переменных, в том числе результаты арифметических операций и модификаторов.
|
||||
|
||||
```smarty
|
||||
{funct arg=true}
|
||||
{funct arg=5}
|
||||
{funct arg=1.2}
|
||||
{funct arg='string'}
|
||||
{funct arg="string this {$var}"}
|
||||
{funct arg=[1,2,34]}
|
||||
{funct arg=$x}
|
||||
{funct arg=$x.c}
|
||||
```
|
||||
|
||||
```smarty
|
||||
{funct arg="ivan"|upper}
|
||||
{funct arg=$a.d.c|lower}
|
||||
```
|
||||
|
||||
```smarty
|
||||
{funct arg=1+2}
|
||||
{funct arg=$a.d.c+4}
|
||||
{funct arg=($a.d.c|count+4)/3}
|
||||
```
|
||||
|
||||
## Static method support
|
||||
|
||||
By default static methods are allowed in templates
|
||||
|
||||
```smarty
|
||||
{Lib\Math::multiple x=3 y=4} static method as tag
|
||||
{Lib\Math::multiple(3,4)} inline static method
|
||||
{12 + Lib\Math::multiple(3,4)}
|
||||
{12 + 3|Lib\Math::multiple:4} static method as modifier
|
||||
```
|
||||
|
||||
You may disable call static methods in template, see in [security options](./settings.md) option `deny_static`
|
||||
|
||||
**TODO**
|
||||
|
||||
## Ignoring template code
|
||||
|
||||
@ -360,7 +554,7 @@ Tags to allow any number of spaces
|
||||
|
||||
### Tag options
|
||||
|
||||
TODO
|
||||
**TODO**
|
||||
|
||||
| name | code | type | description |
|
||||
| ------- | ---- | ----- | ------------ |
|
||||
|
@ -36,7 +36,8 @@ $fenom->setOptions($options);
|
||||
| *force_include* | `Fenom::FORCE_INCLUDE` | стараться по возможности вставить код дочернего шаблона в родительский при подключении шаблона | повышает производительность, увеличивает размер файлов в кеше, уменьшает количество файлов в кеше |
|
||||
| *auto_escape* | `Fenom::AUTO_ESCAPE` | автоматически экранировать HTML сущности при выводе переменных в шаблон | понижает производительность |
|
||||
| *force_verify* | `Fenom::FORCE_VERIFY` | автоматически проверять существование переменной перед использованием в шаблоне | понижает производительность |
|
||||
| *disable_statics* | `Fenom::DENY_STATICS` | отключает воззможность вызова статических методов в шаблоне | |
|
||||
| *disable_php_calls* | `Fenom::DENY_PHP_CALLS` | отключает возможность вызова статических методов и функций в шаблоне | |
|
||||
| *disable_statics* | `Fenom::DENY_STATICS` | устаревшее название disable_php_calls | |
|
||||
| *strip* | `Fenom::AUTO_STRIP` | удаляет лишиние пробелы в шаблоне | уменьшает размер кеша |
|
||||
|
||||
```php
|
||||
@ -48,5 +49,9 @@ $fenom->setOptions(array(
|
||||
$fenom->setOptions(Fenom::AUTO_RELOAD | Fenom::FORCE_INCLUDE);
|
||||
```
|
||||
|
||||
```php
|
||||
$fenom->addCallFilter('View\Widget\*::get*')
|
||||
```
|
||||
|
||||
**Замечание**
|
||||
По умолчанию все параметры деактивированы.
|
||||
|
@ -1,8 +1,6 @@
|
||||
Расширение Fenom
|
||||
================
|
||||
|
||||
*TODO*
|
||||
|
||||
# Добавление тегов
|
||||
|
||||
В шаблонизаторе принято различать два типа тегов: _компиляторы_ и _функции_.
|
||||
@ -116,11 +114,27 @@ $fenom->addModifier('my_modifier', function ($variable, $param1, $param2) {
|
||||
# Расширение тестовго оператора
|
||||
|
||||
```php
|
||||
$fenom->addTest($name, $code);
|
||||
?>
|
||||
$fenom->addTest(string $name, string $code);
|
||||
```
|
||||
`$code` - PHP код для условия, с маркером для замены на значение или переменную.
|
||||
Например, тест на целое число `is int` можно добавить как `$fenom->addTest('int', 'is_int(%s)')`.
|
||||
В шаблоне тесты выглядит как `{$a is int}`, а после компиляции выглядит приблизительно так - `is_int($a)`.
|
||||
|
||||
# Расширение глобальной переменной или функции
|
||||
|
||||
Fenom обладает определенным набором глобальных переменных и функций. Однако их может не хватать для удобной работы с шаблонами.
|
||||
В этом случае потребуется добавить, переопределить или удалить существующие глобальные переменные или функции.
|
||||
Метод `Fenom::addAccessor(string $name, callable $parser)` позволяет добавить свой обработчик на не известную глобальную переменную или функцию.
|
||||
|
||||
```php
|
||||
$fenom->addAccessor('project', function (Fenom\Tokenizer $tokens) { /* code */ });
|
||||
```
|
||||
|
||||
# Расширение глобальной переменной
|
||||
Указанный вторым аргументом, парсер будет вызван при встречи компилятором конструкции `{$.project}`.
|
||||
Парсеры вызываются только на момент сборки шаблона, а не во время его выполенения.
|
||||
|
||||
Через метод `Fenom::addAccessor($name, $parser)` можно переопределить уже любую другую существующую глобальную переменную или функцию.
|
||||
Метод `Fenom::removeAccessor($name)` позволяет удалить любую определенную глобальную переменную или функцию по ее имени.
|
||||
|
||||
# Источники шаблонов
|
||||
|
||||
|
@ -127,11 +127,13 @@ Fenom поддерживает префиксные и постфиксные о
|
||||
* `--$a` - префиксный декремент, уменьшает $a на единицу, затем возвращает значение $a.
|
||||
* `$a--` - постфиксный декремент, возвращает значение $a, затем уменьшает $a на единицу.
|
||||
|
||||
### Строковый оператор
|
||||
### Строковые операторы
|
||||
|
||||
Оператор объединения `~` возвращает строку, представляющую собой соединение левого и правого аргумента.
|
||||
|
||||
`$a ~ $b` - возвращает результат объединения сток `$a` и `$b`
|
||||
* `$a ~ $b` - возвращает результат объединения сток `$a` и `$b`
|
||||
* `$a ~~ $b` - возвращает результат объединения сток `$a` и `$b` через пробел
|
||||
* `$a ~= $b` - присвоение с объединением
|
||||
|
||||
### Тернарные операторы
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
### Теги
|
||||
|
||||
[Использование](./syntax.md#tags) тегов.
|
||||
[Использование](./syntax.md#Теги) тегов.
|
||||
|
||||
* [set](./tags/set.md), `add` и `var` — определение значения переменной
|
||||
* [if](./tags/if.md), `elseif` и `else` — условный оператор
|
||||
@ -40,7 +40,7 @@
|
||||
* [autoescape](./tags/autoescape.md) — экранирует фрагмент шаблона
|
||||
* [raw](./tags/raw.md) — отключает экранирование фрагмента шаблона
|
||||
* [unset](./tags/unset.md) — удаляет переменные
|
||||
* или [добавте](./ext/extend.md#add-tags) свои
|
||||
* или [добавте](./ext/extend.md#Добавление-тегов) свои
|
||||
|
||||
|
||||
***
|
||||
@ -68,7 +68,7 @@
|
||||
* [join](./mods/join.md) — объединяет массив в строку
|
||||
* так же разрешены функции: `json_encode`, `json_decode`, `count`, `is_string`, `is_array`, `is_numeric`, `is_int`, `is_object`,
|
||||
`strtotime`, `gettype`, `is_double`, `ip2long`, `long2ip`, `strip_tags`, `nl2br`
|
||||
* или [добавте](./ext/extend.md#add-modifiers) свои
|
||||
* или [добавте](./ext/extend.md#Добавление-модификаторов) свои
|
||||
|
||||
***
|
||||
|
||||
@ -79,7 +79,7 @@
|
||||
* [Операторы сравнения](./operators.md#Операторы-сравнения) — `>`, `>=`, `<`, `<=`, `==`, `!=`, `!==`, `<>`
|
||||
* [Битовые операторы](./operators.md#Битовые-операторы) — `|`, `&`, `^`, `~$var`, `>>`, `<<`
|
||||
* [Операторы присвоения](./operators.md#Операторы-присвоения) — `=`, `+=`, `-=`, `*=`, `/=`, `%=`, `&=`, `|=`, `^=`, `>>=`, `<<=`
|
||||
* [Строковый оператор](./operators.md#Строковый-оператор) — `$str1 ~ $str2`
|
||||
* [Строковые операторы](./operators.md#Строковые-операторы) — `$str1 ~ $str2`, `$str1 ~~ $str2`, `$str1 ~= $str2`
|
||||
* [Тернарные операторы](./operators.md#Тернарные-операторы) — `$a ? $b : $c`, `$a ! $b : $c`, `$a ?: $c`, `$a !: $c`
|
||||
* [Проверяющие операторы](./operators.md#Проверяющие-операторы) — `$var?`, `$var!`
|
||||
* [Оператор тестирования](./operators.md#Оператор-тестирования) — `is`, `is not`
|
||||
|
@ -2,7 +2,7 @@
|
||||
=========
|
||||
|
||||
По синтаксису шаблона Fenom похож на [Smarty](http://www.smarty.net/), но обладает рядом улучшений.
|
||||
Все теги шаблонизатора заключаются в фигурные скобки: `{` — открытие тега и `}` — закрытие тега.
|
||||
Все теги шаблонизатора заключаются в фигрные скобки: `{` — открытие тега и `}` — закрытие тега.
|
||||
|
||||
**Замечание**
|
||||
Хоть Fenom и позаимствовал синтаксис Smarty, но он не заимствовал теги Smarty как есть.
|
||||
@ -29,7 +29,7 @@
|
||||
<div class="user">Hello, <a href="/users/17">Bzick</a>.</div>
|
||||
```
|
||||
|
||||
Переменные могут быть массивом. В этом случае обращение по ключу происходит через оператор `.` или, как в PHP, через операторы `[` и `]`
|
||||
Переменные могут быть массивом. В этом случае обращение по ключу происходит через опертор `.` или, как в PHP, через операторы `[` и `]`
|
||||
```smarty
|
||||
<div class="user">Hello, <a href="/users/{$user.id}">{$user.name}</a>.</div>
|
||||
```
|
||||
@ -38,12 +38,12 @@
|
||||
<div class="user">Hello, <a href="/users/{$user['id']}">{$user['name']}</a>.</div>
|
||||
```
|
||||
|
||||
В случае объекта, доступ к его свойствам осуществляется так как и в PHP — через оператор `->`:
|
||||
В случае объекта, доступ к его свойствам осущесвляется так как и в 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>
|
||||
```
|
||||
@ -53,7 +53,7 @@
|
||||
Что бы избежать фатальной ошибки определите метод `__call` у класса объекта.
|
||||
Вызов методов в шаблоне можно вообще выключить в [настройках](./docs/configuration.md).
|
||||
|
||||
Ниже приведены комбинированные примеры работы с переменными:
|
||||
Ниже приведены комбинированые примеры работы с переменными:
|
||||
|
||||
```smarty
|
||||
{$foo.bar.baz}
|
||||
@ -79,27 +79,34 @@
|
||||
|
||||
### Системная переменная
|
||||
|
||||
Безымянная системная переменная начинается с `$.` и предоставляет доступ к глобальным системным переменным и системной информации:
|
||||
Безименная системная переменная начинается с `$.` и предоставляет доступ к глобальным системным переменным и системной информации:
|
||||
|
||||
* `$.get` — `$_GET`.
|
||||
* `$.post` — `$_POST`.
|
||||
* `$.cookie` — `$_COOKIE`.
|
||||
* `$.session` — `$_SESSION`.
|
||||
* `$.globals` — `$GLOBALS`.
|
||||
* `$.request` — `$_REQUEST`.
|
||||
* `$.files` — `$_FILES`.
|
||||
* `$.server` — `$_SERVER`.
|
||||
* `$.env` — `$_ENV`.
|
||||
* `$.env` — массив `$_ENV`.
|
||||
* `$.get` — массив `$_GET`.
|
||||
* `$.post` — массив `$_POST`.
|
||||
* `$.files` — массив `$_FILES`.
|
||||
* `$.cookie` — массив `$_COOKIE`.
|
||||
* `$.server` — массив `$_SERVER`.
|
||||
* `$.session` — массив `$_SESSION`.
|
||||
* `$.globals` — массив `$GLOBALS`.
|
||||
* `$.request` — массив `$_REQUEST`.
|
||||
* `$.tpl.name` возвращает текущее название шаблона.
|
||||
* `$.tpl.schema` возвращает код провайдера шаблона.
|
||||
* `$.tpl.basename` возвращает текущее название шаблона без схемы.
|
||||
* `$.tpl.scm` возвращает схему шаблона.
|
||||
* `$.tpl.options` возвращает параметры шбалона в виде целого числа.
|
||||
* `$.tpl.depends` возвращает массив шаблонов на которые ссылается текущий шаблон.
|
||||
* `$.tpl.time` возвращает штамп времени когда шаблон последний раз менялся
|
||||
* `$.version` возвращает версию Fenom.
|
||||
* `$.const` обращение к PHP константе: `$.const.PHP_EOL` .
|
||||
|
||||
```smarty
|
||||
{if $.get.debug? && $.const.DEBUG}
|
||||
...
|
||||
{/if}
|
||||
```
|
||||
* `$.const` обращение к PHP константе: `$.const.PHP_EOL` обращение к константе `PHP_EOL`. Поддерживается пространство имен
|
||||
которое разделяется через точку: `$.const.Storage.FS::DIR_SEPARATOR` обращение к PHP константе `Storage\FS::DIR_SEPARATOR`
|
||||
если такой констатнты нет будет взята константа `Storage\FS\DIR_SEPARATOR`.
|
||||
* `$.php` обращение к статическомому методу. `$.php.Storage.FS::put($filename, $data)` обращение к методу `Storage\FS::put($filename, $data)`.
|
||||
`$.php.Storage.FS.put($filename, $data)` `Storage\FS\put($filename, $data)`
|
||||
* Системная функция `$.fetch($name, $values)` реализует метод Fenom::fetch() в шаблоне. `$name` — имя шаблона,
|
||||
`$values` — дополнительные переменные, которые будут добавлены к существующим.
|
||||
Функция позволяет получить резуьтат работы шаблона в переменную.
|
||||
* так же вы можете [добавить](./ext/extend.md#Расширение-глобальной-переменной-или-функции) свои системные переменные и функции
|
||||
|
||||
|
||||
## Скалярные значения
|
||||
|
||||
@ -110,7 +117,20 @@
|
||||
#### Двойные кавычки
|
||||
|
||||
Если строка заключена в двойные кавычки `"`, Fenom распознает большее количество управляющих последовательностей для специальных символов:
|
||||
`\n`, `\r`, `\t`, `\v`, `\e`, `\f`, `\\`, `\$`, `\"`, `\[0-7]{1,3}`, `\x[0-9A-Fa-f]{1,2}`.
|
||||
|
||||
| Последовательность | Значение |
|
||||
|---------------------|----------|
|
||||
| `\n` | новая строка (LF или 0x0A (10) в ASCII)
|
||||
| `\r` | возврат каретки (CR или 0x0D (13) в ASCII)
|
||||
| `\t` | горизонтальная табуляция (HT или 0x09 (9) в ASCII)
|
||||
| `\v` | вертикальная табуляция (VT или 0x0B (11) в ASCII)
|
||||
| `\f` | подача страницы (FF или 0x0C (12) в ASCII)
|
||||
| `\\` | обратная косая черта
|
||||
| `\$` | знак доллара
|
||||
| `\"` | двойная кавычка
|
||||
| `\[0-7]{1,3}` | последовательность символов, соответствующая регулярному выражению символа в восьмеричной системе счисления
|
||||
| `\x[0-9A-Fa-f]{1,2}`| последовательность символов, соответствующая регулярному выражению символа в шестнадцатеричной системе счисления
|
||||
|
||||
Но самым важным свойством строк в двойных кавычках является обработка переменных.
|
||||
Существует два типа синтаксиса: простой и сложный. Простой синтаксис более легок и удобен.
|
||||
Он дает возможность обработки переменной, значения массива или свойства объекта с минимумом усилий.
|
||||
@ -168,22 +188,23 @@
|
||||
### Целые числа
|
||||
|
||||
Целые числа могут быть указаны в десятичной (основание 10), шестнадцатеричной (основание 16),
|
||||
восьмеричной (основание 8) или двоичной (основание 2) системе счисления, с необязательным предшествующим знаком (- или +).
|
||||
восьмеричной (основание 8) или двоичной (основание 2) системе счисления, с необязательным предшествующим знаком (`-` или `+`).
|
||||
|
||||
Для записи в восьмеричной системе счисления, необходимо поставить пред числом 0 (ноль). Для записи в шестнадцатеричной системе счисления, необходимо поставить перед числом 0x.
|
||||
Для записи в восьмеричной системе счисления, необходимо поставить пред числом 0 (ноль).
|
||||
Для записи в шестнадцатеричной системе счисления, необходимо поставить перед числом 0x.
|
||||
Для записи в двоичной системе счисления, необходимо поставить перед числом 0b
|
||||
|
||||
```smarty
|
||||
{var $a = 1234} // десятичное число
|
||||
{var $a = -123} // отрицательное число
|
||||
{var $a = 0123} // восьмеричное число (эквивалентно 83 в десятичной системе)
|
||||
{var $a = 0x1A} // шестнадцатеричное число (эквивалентно 26 в десятичной системе)
|
||||
{var $a = 0b11111111} // двоичное число (эквивалентно 255 в десятичной системе)
|
||||
{var $a = 1234} десятичное число
|
||||
{var $a = -123} отрицательное число
|
||||
{var $a = 0123} восьмеричное число (эквивалентно 83 в десятичной системе)
|
||||
{var $a = 0x1A} шестнадцатеричное число (эквивалентно 26 в десятичной системе)
|
||||
{var $a = 0b11111111} двоичное число (эквивалентно 255 в десятичной системе)
|
||||
```
|
||||
|
||||
**Замечение**
|
||||
Двоичная запись числа (`0b1011011`) не доступна на старых версиях PHP — 5.3 или ниже.
|
||||
Попытка использовать на старых версия PHP приведет к исключению при компиляциях.
|
||||
Попытка исользовать на старых версия PHP приведет к исключению при компиляциях.
|
||||
|
||||
**Замечение**
|
||||
Размер целого числа зависит от платформы, хотя, как правило, максимальное значение примерно равно 2 миллиардам (это 32-битное знаковое).
|
||||
@ -207,14 +228,16 @@
|
||||
Это простейший тип. Булевое выражает истинность значения. Он может быть либо TRUE либо FALSE.
|
||||
Для указания булевого значения, используйте ключевое слово TRUE или FALSE. Оба регистро-независимы.
|
||||
|
||||
```smarty
|
||||
{set $a = true}
|
||||
```
|
||||
|
||||
### NULL
|
||||
|
||||
Специальное значение NULL представляет собой переменную без значения. NULL - это единственно возможное значение типа null.
|
||||
|
||||
Обычно возникают путаницы между NULL и FALSE, так как по роли они похожи, но различаются по принципу:
|
||||
NULL - это отсутствие присутствия, а FALSE - присутствие отсутствия.
|
||||
Обычно возникают путаницы между NULL и FALSE, так как по роли они похожи, но разлицаются по принципу:
|
||||
NULL - это отсутствие присутствия, а FALSE - присутвие отсутствия.
|
||||
|
||||
### Операции
|
||||
|
||||
@ -253,7 +276,6 @@ NULL - это отсутствие присутствия, а FALSE - прису
|
||||
"foo" => "bar",
|
||||
"bar" => "foo",
|
||||
]}
|
||||
|
||||
```
|
||||
|
||||
`key` может быть либо целым числом, либо строкой. `value` может быть любого типа.
|
||||
@ -264,7 +286,7 @@ NULL - это отсутствие присутствия, а FALSE - прису
|
||||
* Числа с плавающей точкой также будут преобразованы к числу, т.е. дробная часть будет отброшена. Например, ключ со значением `8.7` будет в действительности сохранен со значением `8`.
|
||||
* Булев также преобразовываются к целому числу. Например, ключ со значением `true` будет сохранен со значением `1` и ключ со значением `false` будет сохранен со значением `0`.
|
||||
* NULL будет преобразован к пустой строке. Например, ключ со значением `null` будет в действительности сохранен со значением `""`.
|
||||
* Массивы (тип array) и объекты (тип object) не могут использоваться в качестве ключей. При подобном использовании компилятор будет генерировать предупреждение: Недопустимый тип смещения (Illegal offset type).
|
||||
* Массивы (тип array) и объекты (тип object) не могут использоваться в качестве ключей. При подобном использовании будет генерироваться предупреждение: Недопустимый тип смещения (Illegal offset type).
|
||||
|
||||
Если несколько элементов в объявлении массива используют одинаковый ключ, то только последний будет использоваться, а все другие будут перезаписаны.
|
||||
|
||||
@ -283,9 +305,40 @@ NULL - это отсутствие присутствия, а FALSE - прису
|
||||
Однако такой способ применять не рекомендуется, так как если переменная `$arr` уже содержит некоторое значение (например, строку),
|
||||
то это значение останется на месте и `[]` может на самом деле означать доступ к символу в строке. Лучше инициализировать переменную путем явного присваивания значения.
|
||||
|
||||
## Константы
|
||||
|
||||
Константы - это идентификаторы (имена) простых значений, определенные в PHP.
|
||||
Исходя из их названия, нетрудно понять, что их значение не может изменяться в ходе выполнения шаблона.
|
||||
Имена констант чувствительны к регистру. По принятому соглашению, имена констант всегда пишутся в верхнем регистре.
|
||||
Константы доступны из любого шаблона через глобальную переменную {$.const.*}: `{$.const.PHP_EOL}`.
|
||||
В шаблоне определить константу нельзя.
|
||||
|
||||
## PHP функции и методы
|
||||
|
||||
Fenom предоставляет возможноть обращаться к функиям и методам самого PHP. Использование их в шаблонах не рекомендуется.
|
||||
Используя системную переменную `$.php` можно вызвать любую функцию или метод в шаблоне:
|
||||
|
||||
```smarty
|
||||
{$.php.some_function($a, $b, $c)}
|
||||
```
|
||||
метод вызывается иначе
|
||||
|
||||
```smarty
|
||||
{$.php.MyClass::method($a, $b, $c)}
|
||||
```
|
||||
|
||||
пространство имен указывается перед функций или классом, разделяя точкой вместо обратного слеша:
|
||||
|
||||
```smarty
|
||||
{$.php.My.NS.some_function($a, $b, $c)}
|
||||
{$.php.My.NS.MyClass::method($a, $b, $c)}
|
||||
```
|
||||
|
||||
Вызов функции и методов можно выключить настройкой `???` или ограничить.
|
||||
|
||||
## Модификаторы
|
||||
|
||||
Модификаторы переменных могут быть применены к переменным, пользовательским функциям или строкам.
|
||||
Модификаторы переменных могут быть прмменены к переменным, пользовательским функциям или строкам.
|
||||
Для их применения надо после модифицируемого значения указать символ `|` (вертикальная черта) и название модификатора.
|
||||
Так же модификаторы могут принимать параметры, которые влияют на их поведение.
|
||||
Эти параметры следуют за названием модификатора и разделяются `:` (двоеточием).
|
||||
@ -304,14 +357,14 @@ NULL - это отсутствие присутствия, а FALSE - прису
|
||||
|
||||
## Теги
|
||||
|
||||
Все сущности шаблона можно разбить на две группы:
|
||||
Все сущности шаблона можно разжелить на две группы:
|
||||
|
||||
* заполнитель (placeholder) — вывод переменной в шаблоне, например `{$name}`
|
||||
* тег — конструкция выполняющая некоторые действия, выглядит как именованный заполнитель (placeholder), например `{include $name}`
|
||||
* тег — конструкция, выполняющаяя некоторые действия, которая выглядит как именованный заполнитель (placeholder), например `{include $name}`
|
||||
|
||||
Теги так же можно разделить на две группы:
|
||||
|
||||
* Функии. Тег функции вызывает пользовательскую функцию во время выполнения шаблона, результат функции будет выведен вместо тега.
|
||||
* Функии. Тег функции вызывает пользовательскую во время выполнения шаблона, результат функции будет выведен вместо тега.
|
||||
Пользовательские функции являются дополнительными и могут быть индивидуальными. Они могут быть изменены по вашему желанию, также вы можете создать новые.
|
||||
* Компиляторы. В отличии от функций компиляторы вызываются во время компиляции шаблона и возвращают PHP код, который описывает некоторое действие.
|
||||
Компиляторы и формируют основные конструкции типа `if`, `foreach` и т.д.
|
||||
|
@ -18,6 +18,12 @@
|
||||
Все значения присвоенных переменных восстанавливаются после того, как подключаемый шаблон отработал.
|
||||
Это значит, что вы можете использовать все переменные из подключающего шаблона в подключаемом, но изменения переменных внутри подключаемого шаблона не будут видны внутри подключающего шаблона после команды {include}.
|
||||
|
||||
Если требуется сохранить результат отрисовки шаблона в переменную то используйте `$.fetch($templates, $values)`:
|
||||
|
||||
```smarty
|
||||
{set $data = $.fetch('user.tpl', ["name" => $data.name, "email" => $data.email])}
|
||||
```
|
||||
|
||||
### {insert}
|
||||
|
||||
В отличии от `{include}` тег `{insert}` не вызывает дочерний шаблон во время отрисовки, в ставляет код дочернего шаблона в родительский на момент компиляции.
|
||||
|
@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__.'/../src/Fenom.php';
|
||||
|
||||
\Fenom::registerAutoload();
|
||||
|
||||
$fenom = Fenom::factory(__DIR__.'/templates', __DIR__.'/compiled', Fenom::AUTO_RELOAD | Fenom::AUTO_ESCAPE);
|
||||
|
||||
$fenom->display('greeting.tpl');
|
||||
$fenom = Fenom::factory(__DIR__.'/templates', __DIR__.'/compiled');
|
||||
$fenom->setOptions(Fenom::AUTO_RELOAD | Fenom::AUTO_STRIP);
|
||||
echo($fenom->compile("problem.tpl", false)->getBody());
|
||||
// $fenom->getTemplate("problem.tpl");
|
111
src/Fenom.php
111
src/Fenom.php
@ -13,11 +13,12 @@ use Fenom\Template;
|
||||
/**
|
||||
* Fenom Template Engine
|
||||
*
|
||||
*
|
||||
* @author Ivan Shalganov <a.cobest@gmail.com>
|
||||
*/
|
||||
class Fenom
|
||||
{
|
||||
const VERSION = '2.0';
|
||||
const VERSION = '2.4';
|
||||
/* Actions */
|
||||
const INLINE_COMPILER = 1;
|
||||
const BLOCK_COMPILER = 5;
|
||||
@ -35,8 +36,13 @@ class Fenom
|
||||
const DISABLE_CACHE = 0x400;
|
||||
const FORCE_VERIFY = 0x800;
|
||||
const AUTO_TRIM = 0x1000; // reserved
|
||||
const DENY_STATICS = 0x2000;
|
||||
const DENY_PHP_CALLS = 0x2000;
|
||||
const AUTO_STRIP = 0x4000;
|
||||
/**
|
||||
* Use DENY_PHP_CALLS
|
||||
* @deprecated
|
||||
*/
|
||||
const DENY_STATICS = 0x2000;
|
||||
|
||||
/* Default parsers */
|
||||
const DEFAULT_CLOSE_COMPILER = 'Fenom\Compiler::stdClose';
|
||||
@ -62,6 +68,7 @@ class Fenom
|
||||
"auto_escape" => self::AUTO_ESCAPE,
|
||||
"force_verify" => self::FORCE_VERIFY,
|
||||
"auto_trim" => self::AUTO_TRIM,
|
||||
"disable_php_calls" => self::DENY_PHP_CALLS,
|
||||
"disable_statics" => self::DENY_STATICS,
|
||||
"strip" => self::AUTO_STRIP,
|
||||
);
|
||||
@ -81,6 +88,11 @@ class Fenom
|
||||
*/
|
||||
public $tag_filters = array();
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
public $call_filters = array();
|
||||
|
||||
/**
|
||||
* @var callable[]
|
||||
*/
|
||||
@ -340,6 +352,24 @@ class Fenom
|
||||
'third' => '!(%s %% 3)'
|
||||
);
|
||||
|
||||
protected $_accessors = array(
|
||||
'get' => 'Fenom\Accessor::getVar',
|
||||
'env' => 'Fenom\Accessor::getVar',
|
||||
'post' => 'Fenom\Accessor::getVar',
|
||||
'request' => 'Fenom\Accessor::getVar',
|
||||
'cookie' => 'Fenom\Accessor::getVar',
|
||||
'globals' => 'Fenom\Accessor::getVar',
|
||||
'server' => 'Fenom\Accessor::getVar',
|
||||
'session' => 'Fenom\Accessor::getVar',
|
||||
'files' => 'Fenom\Accessor::getVar',
|
||||
'tpl' => 'Fenom\Accessor::tpl',
|
||||
'version' => 'Fenom\Accessor::version',
|
||||
'const' => 'Fenom\Accessor::constant',
|
||||
'php' => 'Fenom\Accessor::php',
|
||||
'tag' => 'Fenom\Accessor::Tag',
|
||||
'fetch' => 'Fenom\Accessor::Fetch',
|
||||
);
|
||||
|
||||
/**
|
||||
* Just factory
|
||||
*
|
||||
@ -375,6 +405,9 @@ class Fenom
|
||||
$this->_provider = $provider;
|
||||
}
|
||||
|
||||
public function setCachePerms() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set compile directory
|
||||
*
|
||||
@ -510,12 +543,7 @@ class Fenom
|
||||
* @param array $tags
|
||||
* @return Fenom
|
||||
*/
|
||||
public function addBlockCompiler(
|
||||
$compiler,
|
||||
$open_parser,
|
||||
$close_parser = self::DEFAULT_CLOSE_COMPILER,
|
||||
array $tags = array()
|
||||
) {
|
||||
public function addBlockCompiler($compiler, $open_parser, $close_parser = self::DEFAULT_CLOSE_COMPILER, array $tags = array()) {
|
||||
$this->_actions[$compiler] = array(
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => $open_parser,
|
||||
@ -602,12 +630,8 @@ class Fenom
|
||||
* @param callable|string $parser_close
|
||||
* @return Fenom
|
||||
*/
|
||||
public function addBlockFunction(
|
||||
$function,
|
||||
$callback,
|
||||
$parser_open = self::DEFAULT_FUNC_OPEN,
|
||||
$parser_close = self::DEFAULT_FUNC_CLOSE
|
||||
) {
|
||||
public function addBlockFunction($function, $callback, $parser_open = self::DEFAULT_FUNC_OPEN, $parser_close = self::DEFAULT_FUNC_CLOSE)
|
||||
{
|
||||
$this->_actions[$function] = array(
|
||||
'type' => self::BLOCK_FUNCTION,
|
||||
'open' => $parser_open,
|
||||
@ -772,6 +796,53 @@ class Fenom
|
||||
return $this->_options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add global accessor ($.)
|
||||
* @param string $name
|
||||
* @param callable $parser
|
||||
* @return Fenom
|
||||
*/
|
||||
public function addAccessor($name, $parser)
|
||||
{
|
||||
$this->_accessors[$name] = $parser;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove accessor
|
||||
* @param string $name
|
||||
* @return Fenom
|
||||
*/
|
||||
public function removeAccessor($name)
|
||||
{
|
||||
unset($this->_accessors[$name]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an accessor
|
||||
* @param string $name
|
||||
* @return callable
|
||||
*/
|
||||
public function getAccessor($name) {
|
||||
if(isset($this->_accessors[$name])) {
|
||||
return $this->_accessors[$name];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add filter for $.php accessor.
|
||||
* Uses glob syntax.
|
||||
* @param string $pattern
|
||||
* @return $this
|
||||
*/
|
||||
public function addCallFilter($pattern) {
|
||||
$this->call_filters[] = $pattern;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool|string $scm
|
||||
* @return Fenom\ProviderInterface
|
||||
@ -803,7 +874,8 @@ class Fenom
|
||||
/**
|
||||
* Execute template and write result into stdout
|
||||
*
|
||||
* @param string $template name of template
|
||||
* @param string|array $template name of template.
|
||||
* If it is array of names of templates they will be extended from left to right.
|
||||
* @param array $vars array of data for template
|
||||
* @return Fenom\Render
|
||||
*/
|
||||
@ -814,7 +886,8 @@ class Fenom
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $template name of template
|
||||
* @param string|array $template name of template.
|
||||
* If it is array of names of templates they will be extended from left to right.
|
||||
* @param array $vars array of data for template
|
||||
* @return mixed
|
||||
*/
|
||||
@ -826,7 +899,8 @@ class Fenom
|
||||
/**
|
||||
* Creates pipe-line of template's data to callback
|
||||
* @note Method not works correctly in old PHP 5.3.*
|
||||
* @param string $template name of the template
|
||||
* @param string|array $template name of the template.
|
||||
* If it is array of names of templates they will be extended from left to right.
|
||||
* @param callable $callback template's data handler
|
||||
* @param array $vars
|
||||
* @param float $chunk amount of bytes of chunk
|
||||
@ -969,7 +1043,7 @@ class Fenom
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush internal memory template cache
|
||||
* Flush internal template in-memory-cache
|
||||
*/
|
||||
public function flush()
|
||||
{
|
||||
@ -982,6 +1056,7 @@ class Fenom
|
||||
public function clearAllCompiles()
|
||||
{
|
||||
\Fenom\Provider::clean($this->_compile_dir);
|
||||
$this->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
|
143
src/Fenom/Accessor.php
Normal file
143
src/Fenom/Accessor.php
Normal file
@ -0,0 +1,143 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Fenom.
|
||||
*
|
||||
* (c) 2013 Ivan Shalganov
|
||||
*
|
||||
* For the full copyright and license information, please view the license.md
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Fenom;
|
||||
|
||||
use Fenom\Error\UnexpectedTokenException;
|
||||
|
||||
/**
|
||||
* Class Accessor
|
||||
* @package Fenom
|
||||
*/
|
||||
class Accessor {
|
||||
public static $vars = array(
|
||||
'get' => '$_GET',
|
||||
'post' => '$_POST',
|
||||
'session' => '$_SESSION',
|
||||
'cookie' => '$_COOKIE',
|
||||
'request' => '$_REQUEST',
|
||||
'files' => '$_FILES',
|
||||
'globals' => '$GLOBALS',
|
||||
'server' => '$_SERVER',
|
||||
'env' => '$_ENV'
|
||||
);
|
||||
|
||||
/**
|
||||
* Accessor for global variables
|
||||
* @param Tokenizer $tokens
|
||||
* @param Template $tpl
|
||||
*/
|
||||
public static function getVar(Tokenizer $tokens, Template $tpl)
|
||||
{
|
||||
$name = $tokens->prev[Tokenizer::TEXT];
|
||||
if(isset(self::$vars[$name])) {
|
||||
$var = $tpl->parseVariable($tokens, self::$vars[$name]);
|
||||
return "(isset($var) ? $var : null)";
|
||||
} else {
|
||||
throw new UnexpectedTokenException($tokens->back());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for template information
|
||||
* @param Tokenizer $tokens
|
||||
*/
|
||||
public static function tpl(Tokenizer $tokens)
|
||||
{
|
||||
$method = $tokens->skip('.')->need(T_STRING)->getAndNext();
|
||||
if(method_exists('Fenom\Render', 'get'.$method)) {
|
||||
return '$tpl->get'.ucfirst($method).'()';
|
||||
} else {
|
||||
throw new UnexpectedTokenException($tokens->back());
|
||||
}
|
||||
}
|
||||
|
||||
public static function version()
|
||||
{
|
||||
return 'Fenom::VERSION';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Tokenizer $tokens
|
||||
* @return string
|
||||
*/
|
||||
public static function constant(Tokenizer $tokens)
|
||||
{
|
||||
$const = array($tokens->skip('.')->need(Tokenizer::MACRO_STRING)->getAndNext());
|
||||
while($tokens->is('.')) {
|
||||
$const[] = $tokens->next()->need(Tokenizer::MACRO_STRING)->getAndNext();
|
||||
}
|
||||
$const = implode('\\', $const);
|
||||
if($tokens->is(T_DOUBLE_COLON)) {
|
||||
$const .= '::'.$tokens->next()->need(Tokenizer::MACRO_STRING)->getAndNext();
|
||||
}
|
||||
return '@constant('.var_export($const, true).')';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Tokenizer $tokens
|
||||
* @param Template $tpl
|
||||
* @return string
|
||||
*/
|
||||
public static function php(Tokenizer $tokens, Template $tpl)
|
||||
{
|
||||
$callable = array($tokens->skip('.')->need(Tokenizer::MACRO_STRING)->getAndNext());
|
||||
while($tokens->is('.')) {
|
||||
$callable[] = $tokens->next()->need(Tokenizer::MACRO_STRING)->getAndNext();
|
||||
}
|
||||
$callable = implode('\\', $callable);
|
||||
if($tokens->is(T_DOUBLE_COLON)) {
|
||||
$callable .= '::'.$tokens->next()->need(Tokenizer::MACRO_STRING)->getAndNext();
|
||||
}
|
||||
$call_filter = $tpl->getStorage()->call_filters;
|
||||
if($call_filter) {
|
||||
foreach($call_filter as $filter) {
|
||||
if(!fnmatch(addslashes($filter), $callable)) {
|
||||
throw new \LogicException("Callback ".str_replace('\\', '.', $callable)." is not available by settings");
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!is_callable($callable)) {
|
||||
throw new \RuntimeException("PHP method ".str_replace('\\', '.', $callable).' does not exists.');
|
||||
}
|
||||
if($tokens->is('(')) {
|
||||
$arguments = 'array'.$tpl->parseArgs($tokens).'';
|
||||
} else {
|
||||
$arguments = 'array()';
|
||||
}
|
||||
return 'call_user_func_array('.var_export($callable, true).', '.$arguments.')';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor {$.fetch(...)}
|
||||
* @param Tokenizer $tokens
|
||||
* @param Template $tpl
|
||||
* @return string
|
||||
*/
|
||||
public static function fetch(Tokenizer $tokens, Template $tpl)
|
||||
{
|
||||
$tokens->skip('(');
|
||||
$name = $tpl->parsePlainArg($tokens, $static);
|
||||
if($static) {
|
||||
if(!$tpl->getStorage()->templateExists($static)) {
|
||||
throw new \RuntimeException("Template $static not found");
|
||||
}
|
||||
}
|
||||
if($tokens->is(',')) {
|
||||
$tokens->skip()->need('[');
|
||||
$vars = $tpl->parseArray($tokens) . ' + $var';
|
||||
} else {
|
||||
$vars = '$var';
|
||||
}
|
||||
$tokens->skip(')');
|
||||
return '$tpl->getStorage()->fetch('.$name.', '.$vars.')';
|
||||
}
|
||||
}
|
@ -241,7 +241,7 @@ class Compiler
|
||||
*/
|
||||
public static function forOpen(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
$p = array(
|
||||
$p = array(
|
||||
"index" => false,
|
||||
"first" => false,
|
||||
"last" => false,
|
||||
|
@ -9,8 +9,6 @@
|
||||
*/
|
||||
namespace Fenom;
|
||||
|
||||
use Fenom\ProviderInterface;
|
||||
|
||||
/**
|
||||
* Base template provider
|
||||
* @author Ivan Shalganov
|
||||
@ -19,6 +17,8 @@ class Provider implements ProviderInterface
|
||||
{
|
||||
private $_path;
|
||||
|
||||
protected $_clear_cache = false;
|
||||
|
||||
/**
|
||||
* Clean directory from files
|
||||
*
|
||||
@ -75,6 +75,15 @@ class Provider implements ProviderInterface
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable PHP cache for files. PHP cache some operations with files then script works.
|
||||
* @see http://php.net/manual/en/function.clearstatcache.php
|
||||
* @param bool $status
|
||||
*/
|
||||
public function setClearCachedStats($status = true) {
|
||||
$this->_clear_cache = $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get source and mtime of template by name
|
||||
* @param string $tpl
|
||||
@ -84,7 +93,9 @@ class Provider implements ProviderInterface
|
||||
public function getSource($tpl, &$time)
|
||||
{
|
||||
$tpl = $this->_getTemplatePath($tpl);
|
||||
clearstatcache(true, $tpl);
|
||||
if($this->_clear_cache) {
|
||||
clearstatcache(true, $tpl);
|
||||
}
|
||||
$time = filemtime($tpl);
|
||||
return file_get_contents($tpl);
|
||||
}
|
||||
@ -96,7 +107,10 @@ class Provider implements ProviderInterface
|
||||
*/
|
||||
public function getLastModified($tpl)
|
||||
{
|
||||
clearstatcache(true, $tpl = $this->_getTemplatePath($tpl));
|
||||
$tpl = $this->_getTemplatePath($tpl);
|
||||
if($this->_clear_cache) {
|
||||
clearstatcache(true, $tpl);
|
||||
}
|
||||
return filemtime($tpl);
|
||||
}
|
||||
|
||||
@ -158,7 +172,10 @@ class Provider implements ProviderInterface
|
||||
public function verify(array $templates)
|
||||
{
|
||||
foreach ($templates as $template => $mtime) {
|
||||
clearstatcache(true, $template = $this->_path . '/' . $template);
|
||||
$template = $this->_path . '/' . $template;
|
||||
if($this->_clear_cache) {
|
||||
clearstatcache(true, $template);
|
||||
}
|
||||
if (@filemtime($template) !== $mtime) {
|
||||
return false;
|
||||
}
|
||||
|
@ -90,8 +90,7 @@ class Render extends \ArrayObject
|
||||
$this->_time = $props["time"];
|
||||
$this->_depends = $props["depends"];
|
||||
$this->_macros = $props["macros"];
|
||||
// $this->_blocks = $props["blocks"];
|
||||
$this->_code = $code;
|
||||
$this->_code = $code;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -249,19 +248,6 @@ class Render extends \ArrayObject
|
||||
|
||||
public function __get($name)
|
||||
{
|
||||
if ($name == 'info') {
|
||||
return array(
|
||||
'name' => $this->_name,
|
||||
'schema' => $this->_scm,
|
||||
'time' => $this->_time
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public function __isset($name)
|
||||
{
|
||||
return $name == 'info';
|
||||
return $this->$name = null;
|
||||
}
|
||||
}
|
||||
|
@ -268,7 +268,7 @@ class Template extends Render
|
||||
throw new CompileException("Unclosed tag" . (count($_names) > 1 ? "s" : "") . ": " . implode(
|
||||
", ",
|
||||
$_names
|
||||
), 0, 1, $this->_name, $scope->line); // $scope already defined there!
|
||||
), 0, 1, $this->_name, $scope->line); // for PHPStorm: $scope already defined there!
|
||||
}
|
||||
$this->_src = ""; // cleanup
|
||||
if ($this->_post) {
|
||||
@ -343,8 +343,9 @@ class Template extends Render
|
||||
$text = str_replace("<?", '<?php echo "<?"; ?>' . PHP_EOL, $text);
|
||||
}
|
||||
if($this->_options & Fenom::AUTO_STRIP) {
|
||||
$text = preg_replace('/\s+/uS', ' ', $text);
|
||||
$text = preg_replace('/\s*([\pP\pS]+)\s*/uS', '$1', $text);
|
||||
|
||||
$text = preg_replace('/\s+/uS', ' ', str_replace(array("\r", "\n"), " ", $text));
|
||||
// $text = preg_replace('/\s*([\pP\pS]+)\s*/uS', '$1', $text);
|
||||
}
|
||||
$this->_body .= $text;
|
||||
}
|
||||
@ -662,10 +663,6 @@ class Template extends Render
|
||||
// parse term
|
||||
$term = $this->parseTerm($tokens, $var); // term of the expression
|
||||
if ($term !== false) {
|
||||
if ($this->_options & Fenom::FORCE_VERIFY) {
|
||||
$term = '(isset(' . $term . ') ? ' . $term . ' : null)';
|
||||
$var = false;
|
||||
}
|
||||
if ($tokens->is('|')) {
|
||||
$term = $this->parseModifier($tokens, $term);
|
||||
$var = false;
|
||||
@ -728,6 +725,10 @@ class Template extends Render
|
||||
if ($tokens->is(T_LNUMBER, T_DNUMBER)) {
|
||||
$concat[] = "strval(" . $this->parseTerm($tokens) . ")";
|
||||
} else {
|
||||
if($tokens->is('~')) {
|
||||
$tokens->next();
|
||||
$concat[] = " ";
|
||||
}
|
||||
if(!$concat[] = $this->parseTerm($tokens)) {
|
||||
throw new UnexpectedTokenException($tokens);
|
||||
}
|
||||
@ -775,23 +776,37 @@ class Template extends Render
|
||||
}
|
||||
return $this->parseScalar($tokens, true);
|
||||
} elseif ($tokens->is(T_VARIABLE)) {
|
||||
$code = $unary . $this->parseVariable($tokens);
|
||||
$code = $this->parseVariable($tokens);
|
||||
if ($tokens->is("(") && $tokens->hasBackList(T_STRING, T_OBJECT_OPERATOR)) {
|
||||
if ($this->_options & Fenom::DENY_METHODS) {
|
||||
throw new \LogicException("Forbidden to call methods");
|
||||
}
|
||||
$code = $this->parseChain($tokens, $code);
|
||||
return $this->parseChain($tokens, $code);
|
||||
} elseif ($tokens->is(Tokenizer::MACRO_INCDEC)) {
|
||||
$code .= $tokens->getAndNext();
|
||||
if($this->_options & Fenom::FORCE_VERIFY) {
|
||||
return $unary . '(isset(' . $code . ') ? ' . $code . $tokens->getAndNext() . ' : null)';
|
||||
} else {
|
||||
return $unary . $code . $tokens->getAndNext();
|
||||
}
|
||||
} else {
|
||||
$is_var = true;
|
||||
if($this->_options & Fenom::FORCE_VERIFY) {
|
||||
return $unary . '(isset(' . $code . ') ? ' . $code . ' : null)';
|
||||
} else {
|
||||
$is_var = true;
|
||||
return $unary . $code;
|
||||
}
|
||||
}
|
||||
return $code;
|
||||
} elseif ($tokens->is('$')) {
|
||||
$var = $this->parseAccessor($tokens, $is_var);
|
||||
$is_var = false;
|
||||
$var = $this->parseAccessor($tokens);
|
||||
return $unary . $var;
|
||||
} elseif ($tokens->is(Tokenizer::MACRO_INCDEC)) {
|
||||
return $unary . $tokens->getAndNext() . $this->parseVariable($tokens);
|
||||
if($this->_options & Fenom::FORCE_VERIFY) {
|
||||
$var = $this->parseVariable($tokens);
|
||||
return $unary . '(isset(' . $var . ') ? ' . $tokens->getAndNext() . $this->parseVariable($tokens).' : null)';
|
||||
} else {
|
||||
return $unary . $tokens->getAndNext() . $this->parseVariable($tokens);
|
||||
}
|
||||
} elseif ($tokens->is("(")) {
|
||||
$tokens->next();
|
||||
$code = $unary . "(" . $this->parseExpr($tokens) . ")";
|
||||
@ -913,44 +928,18 @@ class Template extends Render
|
||||
|
||||
/**
|
||||
* Parse accessor
|
||||
* @param Tokenizer $tokens
|
||||
* @return string
|
||||
*/
|
||||
public function parseAccessor(Tokenizer $tokens, &$is_var)
|
||||
public function parseAccessor(Tokenizer $tokens)
|
||||
{
|
||||
$is_var = false;
|
||||
$vars = array(
|
||||
'get' => '$_GET',
|
||||
'post' => '$_POST',
|
||||
'session' => '$_SESSION',
|
||||
'cookie' => '$_COOKIE',
|
||||
'request' => '$_REQUEST',
|
||||
'files' => '$_FILES',
|
||||
'globals' => '$GLOBALS',
|
||||
'server' => '$_SERVER',
|
||||
'env' => '$_ENV',
|
||||
'tpl' => '$tpl->info'
|
||||
);
|
||||
if ($this->_options & Fenom::DENY_ACCESSOR) {
|
||||
throw new \LogicException("Accessor are disabled");
|
||||
$accessor = $tokens->need('$')->next()->need('.')->next()->current();
|
||||
$callback = $this->getStorage()->getAccessor($accessor);
|
||||
if($callback) {
|
||||
return call_user_func($callback, $tokens->next(), $this);
|
||||
} else {
|
||||
throw new \RuntimeException("Unknown accessor '$accessor'");
|
||||
}
|
||||
$key = $tokens->need('$')->next()->need('.')->next()->current();
|
||||
$tokens->next();
|
||||
if (isset($vars[$key])) {
|
||||
$is_var = true;
|
||||
return $this->parseVariable($tokens, $vars[$key]);
|
||||
}
|
||||
switch ($key) {
|
||||
case 'const':
|
||||
$tokens->need('.')->next();
|
||||
$var = '@constant(' . var_export($this->parseName($tokens), true) . ')';
|
||||
break;
|
||||
case 'version':
|
||||
$var = '\Fenom::VERSION';
|
||||
break;
|
||||
default:
|
||||
throw new UnexpectedTokenException($tokens->back());
|
||||
}
|
||||
|
||||
return $var;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -11,17 +11,6 @@ namespace Fenom;
|
||||
|
||||
use Fenom\Error\UnexpectedTokenException;
|
||||
|
||||
/**
|
||||
* for PHP <5.4 compatible
|
||||
*/
|
||||
defined('T_INSTEADOF') || define('T_INSTEADOF', 341);
|
||||
defined('T_TRAIT') || define('T_TRAIT', 355);
|
||||
defined('T_TRAIT_C') || define('T_TRAIT_C', 365);
|
||||
/**
|
||||
* for PHP <5.5 compatible
|
||||
*/
|
||||
defined('T_YIELD') || define('T_YIELD', 267);
|
||||
|
||||
/**
|
||||
* Each token have structure
|
||||
* - Token (constant T_* or text)
|
||||
@ -93,154 +82,62 @@ class Tokenizer
|
||||
*/
|
||||
public static $macros = array(
|
||||
self::MACRO_STRING => array(
|
||||
\T_ABSTRACT => 1,
|
||||
\T_ARRAY => 1,
|
||||
\T_AS => 1,
|
||||
\T_BREAK => 1,
|
||||
\T_BREAK => 1,
|
||||
\T_CASE => 1,
|
||||
\T_CATCH => 1,
|
||||
\T_CLASS => 1,
|
||||
\T_CLASS_C => 1,
|
||||
\T_CLONE => 1,
|
||||
\T_CONST => 1,
|
||||
\T_CONTINUE => 1,
|
||||
\T_DECLARE => 1,
|
||||
\T_DEFAULT => 1,
|
||||
\T_DIR => 1,
|
||||
\T_DO => 1,
|
||||
\T_ECHO => 1,
|
||||
\T_ELSE => 1,
|
||||
\T_ELSEIF => 1,
|
||||
\T_EMPTY => 1,
|
||||
\T_ENDDECLARE => 1,
|
||||
\T_ENDFOR => 1,
|
||||
\T_ENDFOREACH => 1,
|
||||
\T_ENDIF => 1,
|
||||
\T_ENDSWITCH => 1,
|
||||
\T_ENDWHILE => 1,
|
||||
\T_EVAL => 1,
|
||||
\T_EXIT => 1,
|
||||
\T_EXTENDS => 1,
|
||||
\T_FILE => 1,
|
||||
\T_FINAL => 1,
|
||||
\T_FOR => 1,
|
||||
\T_FOREACH => 1,
|
||||
\T_FUNCTION => 1,
|
||||
\T_FUNC_C => 1,
|
||||
\T_GLOBAL => 1,
|
||||
\T_GOTO => 1,
|
||||
\T_HALT_COMPILER => 1,
|
||||
\T_IF => 1,
|
||||
\T_IMPLEMENTS => 1,
|
||||
\T_INCLUDE => 1,
|
||||
\T_INCLUDE_ONCE => 1,
|
||||
\T_INSTANCEOF => 1,
|
||||
\T_INSTEADOF => 1,
|
||||
\T_INTERFACE => 1,
|
||||
\T_ISSET => 1,
|
||||
\T_LINE => 1,
|
||||
\T_LIST => 1,
|
||||
\T_LOGICAL_AND => 1,
|
||||
\T_LOGICAL_OR => 1,
|
||||
\T_LOGICAL_XOR => 1,
|
||||
\T_METHOD_C => 1,
|
||||
\T_NAMESPACE => 1,
|
||||
\T_NS_C => 1,
|
||||
\T_NEW => 1,
|
||||
\T_PRINT => 1,
|
||||
\T_PRIVATE => 1,
|
||||
\T_PUBLIC => 1,
|
||||
\T_PROTECTED => 1,
|
||||
\T_REQUIRE => 1,
|
||||
\T_REQUIRE_ONCE => 1,
|
||||
\T_RETURN => 1,
|
||||
\T_RETURN => 1,
|
||||
\T_STRING => 1,
|
||||
\T_SWITCH => 1,
|
||||
\T_THROW => 1,
|
||||
\T_TRAIT => 1,
|
||||
\T_TRAIT_C => 1,
|
||||
\T_TRY => 1,
|
||||
\T_UNSET => 1,
|
||||
\T_USE => 1,
|
||||
\T_VAR => 1,
|
||||
\T_WHILE => 1,
|
||||
\T_YIELD => 1
|
||||
\T_ABSTRACT => 1, \T_ARRAY => 1, \T_AS => 1, \T_BREAK => 1,
|
||||
\T_BREAK => 1, \T_CASE => 1, \T_CATCH => 1, \T_CLASS => 1,
|
||||
\T_CLASS_C => 1, \T_CLONE => 1, \T_CONST => 1, \T_CONTINUE => 1,
|
||||
\T_DECLARE => 1, \T_DEFAULT => 1, \T_DIR => 1, \T_DO => 1,
|
||||
\T_ECHO => 1, \T_ELSE => 1, \T_ELSEIF => 1, \T_EMPTY => 1,
|
||||
\T_ENDDECLARE => 1, \T_ENDFOR => 1, \T_ENDFOREACH => 1, \T_ENDIF => 1,
|
||||
\T_ENDSWITCH => 1, \T_ENDWHILE => 1, \T_EVAL => 1, \T_EXIT => 1,
|
||||
\T_EXTENDS => 1, \T_FILE => 1, \T_FINAL => 1, \T_FOR => 1,
|
||||
\T_FOREACH => 1, \T_FUNCTION => 1, \T_FUNC_C => 1, \T_GLOBAL => 1,
|
||||
\T_GOTO => 1, \T_HALT_COMPILER => 1, \T_IF => 1, \T_IMPLEMENTS => 1,
|
||||
\T_INCLUDE => 1, \T_INCLUDE_ONCE => 1, \T_INSTANCEOF => 1, 341 /* T_INSTEADOF */ => 1,
|
||||
\T_INTERFACE => 1, \T_ISSET => 1, \T_LINE => 1, \T_LIST => 1,
|
||||
\T_LOGICAL_AND => 1, \T_LOGICAL_OR => 1, \T_LOGICAL_XOR => 1, \T_METHOD_C => 1,
|
||||
\T_NAMESPACE => 1, \T_NS_C => 1, \T_NEW => 1, \T_PRINT => 1,
|
||||
\T_PRIVATE => 1, \T_PUBLIC => 1, \T_PROTECTED => 1, \T_REQUIRE => 1,
|
||||
\T_REQUIRE_ONCE => 1, \T_RETURN => 1, \T_RETURN => 1, \T_STRING => 1,
|
||||
\T_SWITCH => 1, \T_THROW => 1, 355 /* T_TRAIT */ => 1, 365 /* T_TRAIT_C */ => 1,
|
||||
\T_TRY => 1, \T_UNSET => 1, \T_USE => 1, \T_VAR => 1,
|
||||
\T_WHILE => 1, 267 /* T_YIELD */ => 1
|
||||
),
|
||||
self::MACRO_INCDEC => array(
|
||||
\T_INC => 1,
|
||||
\T_DEC => 1
|
||||
\T_INC => 1, \T_DEC => 1
|
||||
),
|
||||
self::MACRO_UNARY => array(
|
||||
"!" => 1,
|
||||
"~" => 1,
|
||||
"-" => 1
|
||||
"!" => 1, "~" => 1, "-" => 1
|
||||
),
|
||||
self::MACRO_BINARY => array(
|
||||
\T_BOOLEAN_AND => 1,
|
||||
\T_BOOLEAN_OR => 1,
|
||||
\T_IS_GREATER_OR_EQUAL => 1,
|
||||
\T_IS_EQUAL => 1,
|
||||
\T_IS_IDENTICAL => 1,
|
||||
\T_IS_NOT_EQUAL => 1,
|
||||
\T_IS_NOT_IDENTICAL => 1,
|
||||
\T_IS_SMALLER_OR_EQUAL => 1,
|
||||
\T_LOGICAL_AND => 1,
|
||||
\T_LOGICAL_OR => 1,
|
||||
\T_LOGICAL_XOR => 1,
|
||||
\T_SL => 1,
|
||||
\T_SR => 1,
|
||||
"+" => 1,
|
||||
"-" => 1,
|
||||
"*" => 1,
|
||||
"/" => 1,
|
||||
">" => 1,
|
||||
"<" => 1,
|
||||
"^" => 1,
|
||||
"%" => 1,
|
||||
\T_BOOLEAN_AND => 1, \T_BOOLEAN_OR => 1, \T_IS_GREATER_OR_EQUAL => 1,
|
||||
\T_IS_EQUAL => 1, \T_IS_IDENTICAL => 1, \T_IS_NOT_EQUAL => 1,
|
||||
\T_IS_NOT_IDENTICAL => 1, \T_IS_SMALLER_OR_EQUAL => 1, \T_LOGICAL_AND => 1,
|
||||
\T_LOGICAL_OR => 1, \T_LOGICAL_XOR => 1, \T_SL => 1,
|
||||
\T_SR => 1, "+" => 1, "-" => 1,
|
||||
"*" => 1, "/" => 1, ">" => 1,
|
||||
"<" => 1, "^" => 1, "%" => 1,
|
||||
"&" => 1
|
||||
),
|
||||
self::MACRO_BOOLEAN => array(
|
||||
\T_LOGICAL_OR => 1,
|
||||
\T_LOGICAL_XOR => 1,
|
||||
\T_BOOLEAN_AND => 1,
|
||||
\T_BOOLEAN_OR => 1,
|
||||
\T_LOGICAL_OR => 1, \T_LOGICAL_XOR => 1,
|
||||
\T_BOOLEAN_AND => 1, \T_BOOLEAN_OR => 1,
|
||||
\T_LOGICAL_AND => 1
|
||||
),
|
||||
self::MACRO_MATH => array(
|
||||
"+" => 1,
|
||||
"-" => 1,
|
||||
"*" => 1,
|
||||
"/" => 1,
|
||||
"^" => 1,
|
||||
"%" => 1,
|
||||
"&" => 1,
|
||||
"|" => 1
|
||||
"+" => 1, "-" => 1, "*" => 1,
|
||||
"/" => 1, "^" => 1, "%" => 1,
|
||||
"&" => 1, "|" => 1
|
||||
),
|
||||
self::MACRO_COND => array(
|
||||
\T_IS_EQUAL => 1,
|
||||
\T_IS_IDENTICAL => 1,
|
||||
">" => 1,
|
||||
"<" => 1,
|
||||
\T_SL => 1,
|
||||
\T_SR => 1,
|
||||
\T_IS_NOT_EQUAL => 1,
|
||||
\T_IS_NOT_IDENTICAL => 1,
|
||||
\T_IS_SMALLER_OR_EQUAL => 1,
|
||||
\T_IS_EQUAL => 1, \T_IS_IDENTICAL => 1, ">" => 1,
|
||||
"<" => 1, \T_SL => 1, \T_SR => 1,
|
||||
\T_IS_NOT_EQUAL => 1, \T_IS_NOT_IDENTICAL => 1, \T_IS_SMALLER_OR_EQUAL => 1,
|
||||
),
|
||||
self::MACRO_EQUALS => array(
|
||||
\T_AND_EQUAL => 1,
|
||||
\T_DIV_EQUAL => 1,
|
||||
\T_MINUS_EQUAL => 1,
|
||||
\T_MOD_EQUAL => 1,
|
||||
\T_MUL_EQUAL => 1,
|
||||
\T_OR_EQUAL => 1,
|
||||
\T_PLUS_EQUAL => 1,
|
||||
\T_SL_EQUAL => 1,
|
||||
\T_SR_EQUAL => 1,
|
||||
\T_XOR_EQUAL => 1,
|
||||
'=' => 1,
|
||||
\T_AND_EQUAL => 1, \T_DIV_EQUAL => 1, \T_MINUS_EQUAL => 1,
|
||||
\T_MOD_EQUAL => 1, \T_MUL_EQUAL => 1, \T_OR_EQUAL => 1,
|
||||
\T_PLUS_EQUAL => 1, \T_SL_EQUAL => 1, \T_SR_EQUAL => 1,
|
||||
\T_XOR_EQUAL => 1, '=' => 1,
|
||||
),
|
||||
self::MACRO_SCALAR => array(
|
||||
\T_LNUMBER => 1,
|
||||
|
@ -161,13 +161,13 @@ class TestCase extends \PHPUnit_Framework_TestCase
|
||||
$this->fail("Code $code must be invalid");
|
||||
}
|
||||
|
||||
public function assertRender($tpl, $result, $debug = false)
|
||||
public function assertRender($tpl, $result, array $vars = array(), $debug = false)
|
||||
{
|
||||
$template = $this->fenom->compileCode($tpl);
|
||||
if ($debug) {
|
||||
print_r("\nDEBUG $tpl:\n" . $template->getBody());
|
||||
}
|
||||
$this->assertSame($result, $template->fetch($this->values));
|
||||
$this->assertSame($result, $template->fetch($vars + $this->values));
|
||||
return $template;
|
||||
}
|
||||
|
||||
@ -276,9 +276,13 @@ class TestCase extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
}
|
||||
|
||||
const HELPER_CONSTANT = 'helper.const';
|
||||
|
||||
class Helper
|
||||
{
|
||||
|
||||
const CONSTANT = "helper.class.const";
|
||||
|
||||
public $word = 'helper';
|
||||
|
||||
public function __construct($word)
|
||||
@ -306,3 +310,7 @@ class Helper
|
||||
}
|
||||
}
|
||||
|
||||
function helper_func($string, $pad = 10) {
|
||||
return str_pad($string, $pad, ".");
|
||||
}
|
||||
|
||||
|
230
tests/cases/Fenom/AccessorTest.php
Normal file
230
tests/cases/Fenom/AccessorTest.php
Normal file
@ -0,0 +1,230 @@
|
||||
<?php
|
||||
|
||||
namespace Fenom;
|
||||
|
||||
|
||||
class AccessorTest extends TestCase
|
||||
{
|
||||
public static function providerGetVar()
|
||||
{
|
||||
return array(
|
||||
array("get"),
|
||||
array("post"),
|
||||
array("cookie"),
|
||||
array("request"),
|
||||
array("files"),
|
||||
array("globals"),
|
||||
array("server"),
|
||||
array("session"),
|
||||
array("env"),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerGetVar
|
||||
* @backupGlobals
|
||||
* @param string $var
|
||||
*/
|
||||
public function testGetVar($var)
|
||||
{
|
||||
$_GET['one'] = 'get1';
|
||||
$_POST['one'] = 'post1';
|
||||
$_COOKIE['one'] = 'cookie1';
|
||||
$_REQUEST['one'] = 'request1';
|
||||
$_FILES['one'] = 'files1';
|
||||
$GLOBALS['one'] = 'globals1';
|
||||
$_SERVER['one'] = 'server1';
|
||||
$_SESSION['one'] = 'session1';
|
||||
$_ENV['one'] = 'env1';
|
||||
$this->exec('{$.'.$var.'.one}', self::getVars(), "{$var}1");
|
||||
$this->exec('{$.'.$var.'.undefined}', self::getVars(), "");
|
||||
}
|
||||
|
||||
public static function providerTpl()
|
||||
{
|
||||
return array(
|
||||
array("name"),
|
||||
array("scm"),
|
||||
array("basename"),
|
||||
array("options"),
|
||||
array("time"),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerTpl
|
||||
* @param string $name
|
||||
*/
|
||||
public function testTpl($name)
|
||||
{
|
||||
$this->tpl("accessor.tpl", '{$.tpl.'.$name.'}');
|
||||
$tpl = $this->fenom->setOptions(\Fenom::FORCE_VERIFY)->getTemplate('accessor.tpl');
|
||||
$this->assertSame(strval($tpl->{"get$name"}()), $tpl->fetch(self::getVars()));
|
||||
}
|
||||
|
||||
public function testVersion()
|
||||
{
|
||||
$this->assertRender('{$.version}', \Fenom::VERSION);
|
||||
}
|
||||
|
||||
public static function providerConst()
|
||||
{
|
||||
return array(
|
||||
array("$.const.PHP_VERSION_ID", PHP_VERSION_ID),
|
||||
array('$.const.UNDEFINED', ''),
|
||||
array("$.const.FENOM_RESOURCES", FENOM_RESOURCES),
|
||||
array("$.const.Fenom.HELPER_CONSTANT", HELPER_CONSTANT),
|
||||
array("$.const.Fenom.UNDEFINED", ''),
|
||||
array("$.const.Fenom::VERSION", \Fenom::VERSION),
|
||||
array("$.const.Fenom::UNDEFINED", ''),
|
||||
array("$.const.Fenom.Helper::CONSTANT", Helper::CONSTANT),
|
||||
array("$.const.Fenom.Helper::UNDEFINED", ''),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerConst
|
||||
* @param $tpl
|
||||
* @param $value
|
||||
* @group const
|
||||
*/
|
||||
public function testConst($tpl, $value)
|
||||
{
|
||||
$this->assertRender('{'.$tpl.'}', strval($value));
|
||||
}
|
||||
|
||||
|
||||
public static function providerPHP() {
|
||||
return array(
|
||||
array('$.php.strrev("string")', strrev("string")),
|
||||
array('$.php.strrev("string")', strrev("string"), 'str*'),
|
||||
array('$.php.strrev("string")', strrev("string"), 'strrev'),
|
||||
array('$.php.get_current_user', get_current_user()),
|
||||
array('$.php.Fenom.helper_func("string", 12)', helper_func("string", 12)),
|
||||
array('$.php.Fenom.helper_func("string", 12)', helper_func("string", 12), 'Fenom\\*'),
|
||||
array('$.php.Fenom.helper_func("string", 12)', helper_func("string", 12), 'Fenom\helper_func'),
|
||||
array('$.php.Fenom.helper_func("string", 12)', helper_func("string", 12), '*helper_func'),
|
||||
array('$.php.Fenom.helper_func("string", 12)', helper_func("string", 12), '*'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', TestCase::dots("string")),
|
||||
array('$.php.Fenom.TestCase::dots("string")', TestCase::dots("string"), 'Fenom\*'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', TestCase::dots("string"), 'Fenom\TestCase*'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', TestCase::dots("string"), 'Fenom\TestCase::*'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', TestCase::dots("string"), 'Fenom\*::dots'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', TestCase::dots("string"), 'Fenom\*::*'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', TestCase::dots("string"), 'Fenom\TestCase::dots'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', TestCase::dots("string"), '*::dots'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', TestCase::dots("string"), '*'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerPHP
|
||||
* @group php
|
||||
*/
|
||||
public function testPHP($tpl, $result, $mask = null) {
|
||||
if($mask) {
|
||||
$this->fenom->addCallFilter($mask);
|
||||
}
|
||||
$this->assertRender('{'.$tpl.'}', $result);
|
||||
}
|
||||
|
||||
public static function providerPHPInvalid() {
|
||||
return array(
|
||||
array('$.php.aaa("string")', 'Fenom\Error\CompileException', 'PHP method aaa does not exists'),
|
||||
array('$.php.strrev("string")', 'Fenom\Error\SecurityException', 'Callback strrev is not available by settings', 'strrevZ'),
|
||||
array('$.php.strrev("string")', 'Fenom\Error\SecurityException', 'Callback strrev is not available by settings', 'str*Z'),
|
||||
array('$.php.strrev("string")', 'Fenom\Error\SecurityException', 'Callback strrev is not available by settings', '*Z'),
|
||||
array('$.php.Fenom.aaa("string")', 'Fenom\Error\CompileException', 'PHP method Fenom.aaa does not exists'),
|
||||
array('$.php.Fenom.helper_func("string")', 'Fenom\Error\SecurityException', 'Callback Fenom.helper_func is not available by settings', 'Reflection\*'),
|
||||
array('$.php.Fenom.helper_func("string")', 'Fenom\Error\SecurityException', 'Callback Fenom.helper_func is not available by settings', 'Fenom\*Z'),
|
||||
array('$.php.Fenom.helper_func("string")', 'Fenom\Error\SecurityException', 'Callback Fenom.helper_func is not available by settings', 'Fenom\*::*'),
|
||||
array('$.php.TestCase::aaa("string")', 'Fenom\Error\CompileException', 'PHP method TestCase::aaa does not exists'),
|
||||
array('$.php.Fenom.TestCase::aaa("string")', 'Fenom\Error\CompileException', 'PHP method Fenom.TestCase::aaa does not exists'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', 'Fenom\Error\SecurityException', 'Callback Fenom.TestCase::dots is not available by settings', 'Reflection\*'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', 'Fenom\Error\SecurityException', 'Callback Fenom.TestCase::dots is not available by settings', 'Fenom\*Z'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', 'Fenom\Error\SecurityException', 'Callback Fenom.TestCase::dots is not available by settings', 'Fenom\*::get*'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', 'Fenom\Error\SecurityException', 'Callback Fenom.TestCase::dots is not available by settings', 'Fenom\TestCase::get*'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', 'Fenom\Error\SecurityException', 'Callback Fenom.TestCase::dots is not available by settings', 'Fenom\TestCase::*Z'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', 'Fenom\Error\SecurityException', 'Callback Fenom.TestCase::dots is not available by settings', '*::*Z'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerPHPInvalid
|
||||
* @group php
|
||||
*/
|
||||
public function testPHPInvalid($tpl, $exception, $message, $methods = null) {
|
||||
if($methods) {
|
||||
$this->fenom->addCallFilter($methods);
|
||||
}
|
||||
$this->execError('{'.$tpl.'}', $exception, $message);
|
||||
}
|
||||
|
||||
|
||||
public static function providerAccessor()
|
||||
{
|
||||
return array(
|
||||
array('{$.get.one}', 'get1'),
|
||||
array('{$.post.one}', 'post1'),
|
||||
array('{$.request.one}', 'request1'),
|
||||
array('{$.session.one}', 'session1'),
|
||||
array('{$.files.one}', 'files1'),
|
||||
array('{$.globals.one}', 'globals1'),
|
||||
array('{$.cookie.one}', 'cookie1'),
|
||||
array('{$.server.one}', 'server1'),
|
||||
array('{"string"|append:"_":$.get.one}', 'string_get1'),
|
||||
array('{$.get.one?}', '1'),
|
||||
array('{$.get.one is set}', '1'),
|
||||
array('{$.get.two is empty}', '1'),
|
||||
array('{$.version}', \Fenom::VERSION),
|
||||
array('{$.tpl.name}', 'runtime.tpl'),
|
||||
array('{$.tpl.time}', '0'),
|
||||
array('{$.tpl.schema}', ''),
|
||||
);
|
||||
}
|
||||
|
||||
public static function providerAccessorInvalid()
|
||||
{
|
||||
return array(
|
||||
array('{$.nope.one}', 'Fenom\Error\CompileException', "Unexpected token 'nope'"),
|
||||
array('{$.get.one}', 'Fenom\Error\SecurityException', 'Accessor are disabled', \Fenom::DENY_ACCESSOR),
|
||||
);
|
||||
}
|
||||
|
||||
public static function providerFetch()
|
||||
{
|
||||
return array(
|
||||
array('{$.fetch("welcome.tpl")}'),
|
||||
array('{set $tpl = "welcome.tpl"}{$.fetch($tpl)}'),
|
||||
array('{$.fetch("welcome.tpl", ["username" => "Bzick", "email" => "bzick@dev.null"])}'),
|
||||
array('{set $tpl = "welcome.tpl"}{$.fetch($tpl, ["username" => "Bzick", "email" => "bzick@dev.null"])}'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group fetch
|
||||
* @dataProvider providerFetch
|
||||
*/
|
||||
public function testFetch($code)
|
||||
{
|
||||
$this->tpl('welcome.tpl', '<b>Welcome, {$username} ({$email})</b>');
|
||||
$values = array('username' => 'Bzick', 'email' => 'bzick@dev.null');
|
||||
$this->assertRender($code, $this->fenom->fetch('welcome.tpl', $values), $values);
|
||||
}
|
||||
|
||||
public static function providerFetchInvalid()
|
||||
{
|
||||
return array(
|
||||
array('{$.fetch("welcome_.tpl")}', 'Fenom\Error\CompileException', "Template welcome_.tpl not found"),
|
||||
array('{$.fetch("welcome_.tpl", [])}', 'Fenom\Error\CompileException', "Template welcome_.tpl not found"),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group fetchInvalid
|
||||
* @dataProvider providerFetchInvalid
|
||||
*/
|
||||
public function testFetchInvalidTpl($tpl, $exception, $message) {
|
||||
$this->execError($tpl, $exception, $message);
|
||||
}
|
||||
}
|
29
tests/cases/Fenom/SandboxTest.php
Normal file
29
tests/cases/Fenom/SandboxTest.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Fenom;
|
||||
|
||||
|
||||
class SandboxTest extends TestCase {
|
||||
|
||||
public function test()
|
||||
{
|
||||
|
||||
|
||||
// $this->assertEquals([1, 2, 4, "as" => 767, "df" => ["qert"]], [1, 2, 4, "as" => 767, "df" => ["qet"]]);
|
||||
// $this->fenom->addBlockCompiler('php', 'Fenom\Compiler::nope', function ($tokens, Tag $tag) {
|
||||
// return '<?php ' . $tag->cutContent();
|
||||
// });
|
||||
// $this->tpl('welcome.tpl', '{$a}');
|
||||
// try {
|
||||
// var_dump($this->fenom->compileCode('{$.fetch("welcome.tpl", ["a" => 1])}')->getBody());
|
||||
// } catch (\Exception $e) {
|
||||
// print_r($e->getMessage() . "\n" . $e->getTraceAsString());
|
||||
// while ($e->getPrevious()) {
|
||||
// $e = $e->getPrevious();
|
||||
// print_r("\n\n" . $e->getMessage() . " in {$e->getFile()}:{$e->getLine()}\n" . $e->getTraceAsString());
|
||||
// }
|
||||
// }
|
||||
// exit;
|
||||
}
|
||||
|
||||
}
|
@ -17,15 +17,7 @@ class TemplateTest extends TestCase
|
||||
{
|
||||
parent::setUp();
|
||||
$this->tpl('welcome.tpl', '<b>Welcome, {$username} ({$email})</b>');
|
||||
$_GET['one'] = 'get1';
|
||||
$_POST['one'] = 'post1';
|
||||
$_REQUEST['one'] = 'request1';
|
||||
$_FILES['one'] = 'files1';
|
||||
$_SERVER['one'] = 'server1';
|
||||
$_SESSION['one'] = 'session1';
|
||||
$GLOBALS['one'] = 'globals1';
|
||||
$_ENV['one'] = 'env1';
|
||||
$_COOKIE['one'] = 'cookie1';
|
||||
|
||||
}
|
||||
|
||||
public static function providerVars()
|
||||
@ -441,6 +433,7 @@ class TemplateTest extends TestCase
|
||||
'if: block1 end'
|
||||
),
|
||||
array('if: {if $unexist} block1 {else} block2 {/if} end', $a, 'if: block2 end', Fenom::FORCE_VERIFY),
|
||||
array('if: {if !$unexist} block1 {else} block2 {/if} end', $a, 'if: block1 end', Fenom::FORCE_VERIFY),
|
||||
);
|
||||
}
|
||||
|
||||
@ -1217,40 +1210,6 @@ class TemplateTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
public static function providerAccessor()
|
||||
{
|
||||
return array(
|
||||
array('{$.get.one}', 'get1'),
|
||||
array('{$.post.one}', 'post1'),
|
||||
array('{$.request.one}', 'request1'),
|
||||
array('{$.session.one}', 'session1'),
|
||||
array('{$.files.one}', 'files1'),
|
||||
array('{$.globals.one}', 'globals1'),
|
||||
array('{$.cookie.one}', 'cookie1'),
|
||||
array('{$.server.one}', 'server1'),
|
||||
array('{$.const.PHP_EOL}', PHP_EOL),
|
||||
array('{$.const.MY}', ''),
|
||||
array('{$.version}', Fenom::VERSION),
|
||||
array('{"string"|append:"_":$.get.one}', 'string_get1'),
|
||||
array('{$.get.one?}', '1'),
|
||||
array('{$.get.one is set}', '1'),
|
||||
array('{$.get.two is empty}', '1'),
|
||||
array('{$.version}', Fenom::VERSION),
|
||||
array('{$.tpl?}', '1'),
|
||||
array('{$.tpl.name}', 'runtime.tpl'),
|
||||
array('{$.tpl.time}', '0'),
|
||||
array('{$.tpl.schema}', ''),
|
||||
);
|
||||
}
|
||||
|
||||
public static function providerAccessorInvalid()
|
||||
{
|
||||
return array(
|
||||
array('{$.nope.one}', 'Fenom\Error\CompileException', "Unexpected token 'nope'"),
|
||||
array('{$.get.one}', 'Fenom\Error\SecurityException', 'Accessor are disabled', Fenom::DENY_ACCESSOR),
|
||||
);
|
||||
}
|
||||
|
||||
public function providerStatic()
|
||||
{
|
||||
return array(
|
||||
@ -1622,19 +1581,19 @@ class TemplateTest extends TestCase
|
||||
* @group accessor
|
||||
* @dataProvider providerAccessor
|
||||
*/
|
||||
public function testAccessor($code, $result)
|
||||
{
|
||||
$this->exec($code, self::getVars(), $result);
|
||||
}
|
||||
// public function testAccessor($code, $result)
|
||||
// {
|
||||
// $this->exec($code, self::getVars(), $result);
|
||||
// }
|
||||
|
||||
/**
|
||||
* @group accessor
|
||||
* @dataProvider providerAccessorInvalid
|
||||
*/
|
||||
public function testAccessorInvalid($code, $exception, $message, $options = 0)
|
||||
{
|
||||
$this->execError($code, $exception, $message, $options);
|
||||
}
|
||||
// public function testAccessorInvalid($code, $exception, $message, $options = 0)
|
||||
// {
|
||||
// $this->execError($code, $exception, $message, $options);
|
||||
// }
|
||||
|
||||
/**
|
||||
* @group static
|
||||
|
@ -96,6 +96,7 @@ class FenomTest extends \Fenom\TestCase
|
||||
public function testCheckMTime()
|
||||
{
|
||||
$this->fenom->setOptions(Fenom::FORCE_COMPILE);
|
||||
$this->fenom->getProvider()->setClearCachedStats();
|
||||
$this->tpl('custom.tpl', 'Custom template');
|
||||
$this->assertSame("Custom template", $this->fenom->fetch('custom.tpl', array()));
|
||||
$tpl = $this->fenom->getTemplate('custom.tpl');
|
||||
@ -324,7 +325,7 @@ class FenomTest extends \Fenom\TestCase
|
||||
<a href="/item/{\$one}">number {\$num.1}</a>
|
||||
</div>
|
||||
TPL;
|
||||
$this->assertRender($tpl, '<div class="item item-one"><a href="/item/1">number one</a></div>');
|
||||
$this->assertRender($tpl, '<div class="item item-one"> <a href="/item/1">number one</a> </div>');
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user