fenom/docs/en/syntax.md

19 KiB
Raw Permalink Blame History

Syntax

Fenom implements Smarty 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.

Note Fenom implements Smarty syntax but not implements Smarty tags, however, some tags very similar. But not so bad, Fenom has the extras that make Fenom like Smarty.

Variable

Variables in Fenom can be either displayed directly or used as arguments for functions, attributes and modifiers, inside conditional expressions, etc.

Use variables

Next example uses simple variables $user_id ans $user_name

<div class="user">Hello, <a href="/users/{$user_id}">{$user_name}</a>.</div>

Example outputs next HTML code:

<div class="user">Hello, <a href="/users/17">Bzick</a>.</div>

You can also reference associative array variables by specifying the key after a dot . symbol or paste key name into square brackets, as in PHP.

<div class="user">Hello, <a href="/users/{$user.id}">{$user.name}</a>.</div>

{$user.id} and {$user['id']} are same:

<div class="user">Hello, <a href="/users/{$user['id']}">{$user['name']}</a>.</div>

Properties of objects assigned from PHP can be referenced by specifying the property name after the -> symbol:

<div class="user">Hello, <a href="/users/{$user->id}">{$user->name}</a>.</div>

Methods of objects defined in PHP can be invoked by specifying the method name after the -> symbol and use parenthesis with arguments:

<div class="user">Hello, <a href="/users/{$user->getId()}">{$user->getName()}</a>.</div>

Note Be careful, Fenom do not checks existence of the method before invoke. To avoid the problem class of the object have to define method __call, which throws an exception, etc. Also you can prohibit method call in settings.

Below is complex example:

{$foo.bar.baz}
{$foo.$bar.$baz}
{$foo[5].baz}
{$foo[5].$baz}
{$foo.bar.baz[4]}
{$foo[ $bar.baz ]}
{$foo[5]}
{$foo.5}
{$foo.bar}
{$foo.'bar'}
{$foo."bar"}
{$foo['bar']}
{$foo["bar"]}
{$foo.$bar}
{$foo[$bar]}
{$foo->bar}
{$foo->bar.buz}
{$foo->bar.buz[ $bar->getId("user") ]}
{$foo->bar(5)->buz(5.5)}

System variable

Unnamed system variable starts with $. and allows access to global system variables and template information:

  • $.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.
  • $.version returns version of the Fenom.
  • $.const paste constant.
{if $.get.debug? && $.const.DEBUG}
   ...
{/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.
  • $.phpcall 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 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.

{"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:

{"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:

{"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.

{'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.

{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:

{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.

{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...

todo

See all operators

Set variable

{var $foo = "bar"}
{var $foo = "bar"|upper} {* apply modifier *}
{var $foo = 5}
{var $foo = $x + $y}
{var $foo = $x.y[z] + $y}
{var $foo = strlen($a)} {* work with functions *}
{var $foo = myfunct( ($x+$y)*3 )}
{var $foo.bar.baz = 1} {* multidimensional value support *}
{var $foo = $object->item->method($y, 'named')} {* work with object fine *}

Using block tag

{var $foo}
    content {$text|truncate:30}
{/var}
{var $foo|truncate:50} {* apply modifier to content *}
    content {$text}
{/var}

Set array

{var $foo = [1, 2, 3]} numeric array
{var $foo = ['y' => 'yellow', 'b' => 'blue']} associative array
{var $foo = [1, [9, 8], 3]} can be nested
{var $foo = [1, $two, $three * 3 + 9]}
{var $foo = [$a, $d.c, $a + $f]}
{var $foo = ['y' => 'yellow', $color|upper => $colors[ $color ]}
{var $foo = [1, [$parent, $a->method()], 3]}

See also {var} documentation.

Scalar values

Strings

When the string in double quotation marks, all the expressions in the string will be run. The result of expressions will be inserted into the string instead it.

{var $foo="Username"}
{var $user.name="Username"}
{"Hi, $foo"}          outputs "Hi, Username"
{"Hi, {$foo}"}        outputs "Hi, Username"
{"Hi, {$user.name}"}  outputs "Hi, Username"
{"Hi, {$user.name|up}"} outputs "Hi, USERNAME"
{"Hi, {$user->getName(true)}"} outputs Hi, Username
{var $message = "Hi, {$user.name}"}

but if use single quote any template expressions will be on display as it is

{'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.

{var $a = 1234} decimal number
{var $a = -123} a negative number
{var $a = 0123} octal number (equivalent to 83 decimal)
{var $a = 0x1A} hexadecimal number (equivalent to 26 decimal)
{var $a = 0b11111111} binary number (equivalent to 255 decimal)

Note The size of an integer is platform-dependent, although a maximum value of about two billion is the usual value (that's 32 bits signed). 64-bit platforms usually have a maximum value of about 9223372036854775807

Warning If an invalid digit is given in an octal integer (i.e. 8 or 9), the rest of the number is ignored.

Floating point numbers

Floating point numbers (also known as "floats", "doubles", or "real numbers") can be specified using any of the following syntaxes:

{var $a = 1.234}
{var $b = 1.2e3}
{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.

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.

{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 ([]).

{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

{$.php.some_function($a, $b, $c)}
{$.php.MyClass::method($a, $b, $c)}
{$.php.My.NS.some_function($a, $b, $c)}
{$.php.My.NS.MyClass::method($a, $b, $c)}

Modifiers

Variable modifiers can be applied to variables, custom functions or strings. To apply a modifier, specify the value followed by a | (pipe) and the modifier name. A modifier may accept additional parameters that affect its behavior. These parameters follow the modifier name and are separated by a : (colon).

{var $foo="User"}
{$foo|upper}            outputs "USER"
{$foo|lower}            outputs "user"
{"{$foo|lower}"}        outputs "user"
{"User"|lower}}         outputs "user"
{$looong_text|truncate:80:"..."}  truncate the text to 80 symbols and append <continue> symbols, like "..."
{$looong_text|lower|truncate:$settings.count:$settings.etc}
{var $foo="Ivan"|upper}    sets $foo value "USER"

List of modifiers

Tags

TODO

Ignoring template code

It is sometimes desirable or even necessary to have ignore sections it would otherwise parse. A classic example is embedding Javascript or CSS code in a template. The problem arises as those languages use the { and } characters which are also the default delimiters for Fenom. Fenom has several solutions:

  1. Uses block tag {ignore} {/ignore}. Anything within {ignore} {/ignore} tags is not interpreted, but displayed as-is.
  2. The { and } braces will be ignored so long as they are surrounded by white space.
  3. Uses tag option :ignore for block tag. Все Fenom теги внутри блока будут проигнорированны

Example:

{ignore}
<style>
	h1 {font-size: 24px; color: #F00;}
</style>
{/ignore}
<script>
	(function (text) {
		var e = document.createElement('P');
		e.innerHTML = text;
		document.body.appendChild(e);
	})('test');
{if:ignore $cdn.yandex}
    var item = {cdn: "//yandex.st/"};
{/if}
</script>

Outputs

<style>
	h1 {font-size: 24px; color: #F00;}
</style>
<script>
	(function (text) {
		var e = document.createElement('P');
		e.innerHTML = text;
		document.body.appendChild(e);
	})('test');
	var item = {cdn: "//yandex.st/"};
</script>

Whitespaces

Tags to allow any number of spaces

{include 'control.tpl'
    $options = $list
    $name    = $cp.name
    $type    = 'select'
    isolate  = true
    disable_static = true
}

{foreach [
    "one"   => 1,
    "two"   => 2,
    "three" => 3
] as $key   => $val}

    {$key}: {$val}

{/foreach}

Tag options

TODO

name code type description
strip s block enable strip option for a block of the template
raw a any ignore escape option
escape e any force escape
ignore i block ignore Fenom syntax
{script:ignore} ... {/script}
{foreach:ignore:strip ...} ... {/foreach}