migrate to php8

This commit is contained in:
ivan shalganov 2023-02-06 23:49:54 +01:00
parent 4cdfd306d9
commit ba1bc18aba
9 changed files with 180 additions and 172 deletions

3
.gitignore vendored
View File

@ -5,4 +5,5 @@ composer.phar
tests/resources/compile/* tests/resources/compile/*
!.gitkeep !.gitkeep
tests/resources/template/* tests/resources/template/*
sandbox/compiled/* sandbox/compiled/*
/.phpunit.result.cache

View File

@ -6,7 +6,7 @@ Fenom - Template Engine for PHP
* **Subject:** Template engine * **Subject:** Template engine
* **Syntax:** Smarty-like * **Syntax:** Smarty-like
* **Documentation:** **[English](./docs/en/readme.md)**, **[Russian](./docs/ru/readme.md)** * **Documentation:** **[English](./docs/en/readme.md)**, **[Russian](./docs/ru/readme.md)**
* **PHP version:** 5.4+ * **PHP version:** 8.0+
* **State:** [![Build Status](https://travis-ci.org/fenom-template/fenom.svg?branch=master)](https://travis-ci.org/fenom-template/fenom) [![Coverage Status](https://coveralls.io/repos/fenom-template/fenom/badge.svg?branch=master)](https://coveralls.io/r/fenom-template/fenom?branch=master) * **State:** [![Build Status](https://travis-ci.org/fenom-template/fenom.svg?branch=master)](https://travis-ci.org/fenom-template/fenom) [![Coverage Status](https://coveralls.io/repos/fenom-template/fenom/badge.svg?branch=master)](https://coveralls.io/r/fenom-template/fenom?branch=master)
* **Version:** [![Latest Stable Version](https://poser.pugx.org/fenom/fenom/v/stable.png)](https://packagist.org/packages/fenom/fenom) * **Version:** [![Latest Stable Version](https://poser.pugx.org/fenom/fenom/v/stable.png)](https://packagist.org/packages/fenom/fenom)
* **Packagist:** [fenom/fenom](https://packagist.org/packages/fenom/fenom) [![Total Downloads](https://poser.pugx.org/fenom/fenom/downloads.png)](https://packagist.org/packages/fenom/fenom) * **Packagist:** [fenom/fenom](https://packagist.org/packages/fenom/fenom) [![Total Downloads](https://poser.pugx.org/fenom/fenom/downloads.png)](https://packagist.org/packages/fenom/fenom)
@ -22,16 +22,10 @@ Fenom - Template Engine for PHP
### Install ### Install
If you use composer in your project then you can to install Fenom as package. If you use composer in your project then you can to install Fenom as package.
However, if you are not using composer you have to configure _autoloader_ to work with Fenom.
Fenom implements the `PSR-0` PHP standard to load classes which are located in the `src/` directory.
Templater already has own autoload-function, to register call method `Fenom::registerAutoload`:
```php
Fenom::registerAutoload();
```
### Setup ### Setup
There is two way to create Fenom instance: There is two-way to create Fenom instance:
* Long way: use operator `new` * Long way: use operator `new`
* Shot way: use static factory-method * Shot way: use static factory-method

View File

@ -751,7 +751,7 @@ class Fenom
* @param Template|null $template * @param Template|null $template
* @return mixed * @return mixed
*/ */
public function getModifier(string $modifier, Fenom\Template $template = null): static public function getModifier(string $modifier, Fenom\Template $template = null): string
{ {
if (isset($this->_modifiers[$modifier])) { if (isset($this->_modifiers[$modifier])) {
return $this->_modifiers[$modifier]; return $this->_modifiers[$modifier];
@ -765,12 +765,12 @@ class Fenom
/** /**
* Modifier autoloader * Modifier autoloader
* @param string $modifier * @param string $modifier
* @param Fenom\Template $template * @param Template $template
* @return bool * @return string|null
*/ */
protected function _loadModifier(string $modifier, Fenom\Template $template): bool protected function _loadModifier(string $modifier, Fenom\Template $template): ?string
{ {
return false; return null;
} }
/** /**

View File

@ -9,6 +9,7 @@
*/ */
namespace Fenom; namespace Fenom;
use Fenom\Error\CompileException;
use Fenom\Error\UnexpectedTokenException; use Fenom\Error\UnexpectedTokenException;
/** /**
@ -16,7 +17,7 @@ use Fenom\Error\UnexpectedTokenException;
* @package Fenom * @package Fenom
*/ */
class Accessor { class Accessor {
public static $vars = array( public static array $vars = array(
'get' => '$_GET', 'get' => '$_GET',
'post' => '$_POST', 'post' => '$_POST',
'session' => '$_SESSION', 'session' => '$_SESSION',
@ -32,10 +33,11 @@ class Accessor {
* @param string $var variable expression on PHP ('App::get("storage")->user') * @param string $var variable expression on PHP ('App::get("storage")->user')
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @param Template $tpl * @param Template $tpl
* @param $is_var * @param bool $is_var
* @return string * @return string
* @throws CompileException
*/ */
public static function parserVar($var, Tokenizer $tokens, Template $tpl, &$is_var) public static function parserVar(string $var, Tokenizer $tokens, Template $tpl, bool &$is_var): string
{ {
$is_var = true; $is_var = true;
return $tpl->parseVariable($tokens, $var); return $tpl->parseVariable($tokens, $var);
@ -47,7 +49,7 @@ class Accessor {
* @param Template $tpl * @param Template $tpl
* @return string * @return string
*/ */
public static function parserCall($call, Tokenizer $tokens, Template $tpl) public static function parserCall(string $call, Tokenizer $tokens, Template $tpl): string
{ {
return $call.$tpl->parseArgs($tokens); return $call.$tpl->parseArgs($tokens);
} }
@ -56,10 +58,11 @@ class Accessor {
* @param string $prop fenom's property name * @param string $prop fenom's property name
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @param Template $tpl * @param Template $tpl
* @param $is_var * @param bool $is_var
* @return string * @return string
* @throws CompileException
*/ */
public static function parserProperty($prop, Tokenizer $tokens, Template $tpl, &$is_var) public static function parserProperty(string $prop, Tokenizer $tokens, Template $tpl, bool &$is_var): string
{ {
$is_var = true; $is_var = true;
return self::parserVar('$tpl->getStorage()->'.$prop, $tokens, $tpl, $is_var); return self::parserVar('$tpl->getStorage()->'.$prop, $tokens, $tpl, $is_var);
@ -71,7 +74,7 @@ class Accessor {
* @param Template $tpl * @param Template $tpl
* @return string * @return string
*/ */
public static function parserMethod($method, Tokenizer $tokens, Template $tpl) public static function parserMethod(string $method, Tokenizer $tokens, Template $tpl): string
{ {
return self::parserCall('$tpl->getStorage()->'.$method, $tokens, $tpl); return self::parserCall('$tpl->getStorage()->'.$method, $tokens, $tpl);
} }
@ -81,13 +84,14 @@ class Accessor {
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @param Template $tpl * @param Template $tpl
* @return string * @return string
* @throws CompileException
*/ */
public static function getVar(Tokenizer $tokens, Template $tpl) public static function getVar(Tokenizer $tokens, Template $tpl): string
{ {
$name = $tokens->prevToken()[Tokenizer::TEXT]; $name = $tokens->prevToken()[Tokenizer::TEXT];
if(isset(self::$vars[$name])) { if(isset(self::$vars[$name])) {
$var = $tpl->parseVariable($tokens, self::$vars[$name]); $var = $tpl->parseVariable($tokens, self::$vars[$name]);
return "(isset($var) ? $var : null)"; return "(($var) ?? null)";
} else { } else {
throw new UnexpectedTokenException($tokens->back()); throw new UnexpectedTokenException($tokens->back());
} }
@ -98,7 +102,7 @@ class Accessor {
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @return string * @return string
*/ */
public static function tpl(Tokenizer $tokens) public static function tpl(Tokenizer $tokens): string
{ {
$method = $tokens->skip('.')->need(T_STRING)->getAndNext(); $method = $tokens->skip('.')->need(T_STRING)->getAndNext();
if(method_exists('Fenom\Render', 'get'.$method)) { if(method_exists('Fenom\Render', 'get'.$method)) {
@ -111,7 +115,7 @@ class Accessor {
/** /**
* @return string * @return string
*/ */
public static function version() public static function version(): string
{ {
return 'Fenom::VERSION'; return 'Fenom::VERSION';
} }
@ -120,9 +124,9 @@ class Accessor {
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @return string * @return string
*/ */
public static function constant(Tokenizer $tokens) public static function constant(Tokenizer $tokens): string
{ {
$const = array($tokens->skip('.')->need(Tokenizer::MACRO_STRING)->getAndNext()); $const = [$tokens->skip('.')->need(Tokenizer::MACRO_STRING)->getAndNext()];
while($tokens->is('.')) { while($tokens->is('.')) {
$const[] = $tokens->next()->need(Tokenizer::MACRO_STRING)->getAndNext(); $const[] = $tokens->next()->need(Tokenizer::MACRO_STRING)->getAndNext();
} }
@ -139,9 +143,9 @@ class Accessor {
* @param Template $tpl * @param Template $tpl
* @return string * @return string
*/ */
public static function call(Tokenizer $tokens, Template $tpl) public static function call(Tokenizer $tokens, Template $tpl): string
{ {
$callable = array($tokens->skip('.')->need(Tokenizer::MACRO_STRING)->getAndNext()); $callable = [$tokens->skip('.')->need(Tokenizer::MACRO_STRING)->getAndNext()];
while($tokens->is('.')) { while($tokens->is('.')) {
$callable[] = $tokens->next()->need(Tokenizer::MACRO_STRING)->getAndNext(); $callable[] = $tokens->next()->need(Tokenizer::MACRO_STRING)->getAndNext();
} }
@ -175,7 +179,7 @@ class Accessor {
* @param Template $tpl * @param Template $tpl
* @return string * @return string
*/ */
public static function fetch(Tokenizer $tokens, Template $tpl) public static function fetch(Tokenizer $tokens, Template $tpl): string
{ {
$tokens->skip('('); $tokens->skip('(');
$name = $tpl->parsePlainArg($tokens, $static); $name = $tpl->parsePlainArg($tokens, $static);
@ -188,7 +192,7 @@ class Accessor {
$tokens->next(); $tokens->next();
if($tokens->is('[')){ if($tokens->is('[')){
$vars = $tpl->parseArray($tokens) . ' + $var'; $vars = $tpl->parseArray($tokens) . ' + $var';
}elseif($tokens->is(T_VARIABLE)){ } elseif($tokens->is(T_VARIABLE)){
$vars = $tpl->parseExpr($tokens) . ' + $var'; $vars = $tpl->parseExpr($tokens) . ' + $var';
} }
} else { } else {
@ -202,9 +206,9 @@ class Accessor {
* Accessor {$.block.NAME} * Accessor {$.block.NAME}
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @param Template $tpl * @param Template $tpl
* @return mixed * @return string
*/ */
public static function block(Tokenizer $tokens, Template $tpl) public static function block(Tokenizer $tokens, Template $tpl): string
{ {
if($tokens->is('.')) { if($tokens->is('.')) {
$name = $tokens->next()->get(Tokenizer::MACRO_STRING); $name = $tokens->next()->get(Tokenizer::MACRO_STRING);

View File

@ -30,7 +30,7 @@ class Compiler
* @throws \LogicException * @throws \LogicException
* @return string * @return string
*/ */
public static function tagInclude(Tokenizer $tokens, Tag $tag) public static function tagInclude(Tokenizer $tokens, Tag $tag): string
{ {
$tpl = $tag->tpl; $tpl = $tag->tpl;
$name = false; $name = false;
@ -72,10 +72,10 @@ class Compiler
* Tag {insert ...} * Tag {insert ...}
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @param Tag $tag * @param Tag $tag
* @throws Error\InvalidUsageException
* @return string * @return string
* @throws Error\InvalidUsageException|CompileException
*/ */
public static function tagInsert(Tokenizer $tokens, Tag $tag) public static function tagInsert(Tokenizer $tokens, Tag $tag): string
{ {
$tpl = $tag->tpl; $tpl = $tag->tpl;
$tpl->parsePlainArg($tokens, $name); $tpl->parsePlainArg($tokens, $name);
@ -95,8 +95,9 @@ class Compiler
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @param Tag $scope * @param Tag $scope
* @return string * @return string
* @throws \Exception
*/ */
public static function ifOpen(Tokenizer $tokens, Tag $scope) public static function ifOpen(Tokenizer $tokens, Tag $scope): string
{ {
$scope["else"] = false; $scope["else"] = false;
return 'if(' . $scope->tpl->parseExpr($tokens) . ') {'; return 'if(' . $scope->tpl->parseExpr($tokens) . ') {';

View File

@ -19,11 +19,11 @@ class Modifier
/** /**
* Date format * Date format
* *
* @param string|int $date * @param int|string $date
* @param string $format * @param string $format
* @return string * @return string
*/ */
public static function dateFormat($date, $format = "%b %e, %Y") public static function dateFormat(int|string $date, string $format = "%b %e, %Y"): string
{ {
if (!is_numeric($date)) { if (!is_numeric($date)) {
$date = strtotime($date); $date = strtotime($date);
@ -39,7 +39,7 @@ class Modifier
* @param string $format * @param string $format
* @return string * @return string
*/ */
public static function date($date, $format = "Y m d") public static function date(string $date, string $format = "Y m d"): string
{ {
if (!is_numeric($date)) { if (!is_numeric($date)) {
$date = strtotime($date); $date = strtotime($date);
@ -55,18 +55,18 @@ class Modifier
* *
* @param string $text * @param string $text
* @param string $type * @param string $type
* @param string $charset * @param string|null $charset
* @return string * @return string
*/ */
public static function escape($text, $type = 'html', $charset = null) public static function escape(string $text, string $type = 'html', string $charset = null): string
{ {
switch (strtolower($type)) { switch (strtolower($type)) {
case "url": case "url":
return urlencode($text); return urlencode($text);
case "html"; case "html";
return htmlspecialchars($text, ENT_COMPAT, $charset ? $charset : \Fenom::$charset); return htmlspecialchars($text, ENT_COMPAT, $charset ?: \Fenom::$charset);
case "js": case "js":
return json_encode($text, 64 | 256); // JSON_UNESCAPED_SLASHES = 64, JSON_UNESCAPED_UNICODE = 256 return json_encode($text, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
default: default:
return $text; return $text;
} }
@ -79,7 +79,7 @@ class Modifier
* @param string $type * @param string $type
* @return string * @return string
*/ */
public static function unescape($text, $type = 'html') public static function unescape(string $text, string $type = 'html'): string
{ {
switch (strtolower($type)) { switch (strtolower($type)) {
case "url": case "url":
@ -96,12 +96,12 @@ class Modifier
* *
* @param string $string text witch will be truncate * @param string $string text witch will be truncate
* @param int $length maximum symbols of result string * @param int $length maximum symbols of result string
* @param string $etc place holder truncated symbols * @param string $etc placeholder truncated symbols
* @param bool $by_words * @param bool $by_words
* @param bool $middle * @param bool $middle
* @return string * @return string
*/ */
public static function truncate($string, $length = 80, $etc = '...', $by_words = false, $middle = false) public static function truncate(string $string, int $length = 80, string $etc = '...', bool $by_words = false, bool $middle = false): string
{ {
if ($middle) { if ($middle) {
if (preg_match('#^(.{' . $length . '}).*?(.{' . $length . '})?$#usS', $string, $match)) { if (preg_match('#^(.{' . $length . '}).*?(.{' . $length . '})?$#usS', $string, $match)) {
@ -134,7 +134,7 @@ class Modifier
* @param bool $to_line strip line ends * @param bool $to_line strip line ends
* @return string * @return string
*/ */
public static function strip($str, $to_line = false) public static function strip(string $str, bool $to_line = false): string
{ {
$str = trim($str); $str = trim($str);
if ($to_line) { if ($to_line) {
@ -149,7 +149,7 @@ class Modifier
* @param mixed $item * @param mixed $item
* @return int * @return int
*/ */
public static function length($item) public static function length(mixed $item): int
{ {
if (is_string($item)) { if (is_string($item)) {
return strlen(preg_replace('#[\x00-\x7F]|[\x80-\xDF][\x00-\xBF]|[\xE0-\xEF][\x00-\xBF]{2}#s', ' ', $item)); return strlen(preg_replace('#[\x00-\x7F]|[\x80-\xDF][\x00-\xBF]|[\xE0-\xEF][\x00-\xBF]{2}#s', ' ', $item));
@ -168,13 +168,13 @@ class Modifier
* @param mixed $haystack * @param mixed $haystack
* @return bool * @return bool
*/ */
public static function in($value, $haystack) public static function in(mixed $value, mixed $haystack): bool
{ {
if(is_scalar($value)) { if(is_scalar($value)) {
if (is_array($haystack)) { if (is_array($haystack)) {
return in_array($value, $haystack) || array_key_exists($value, $haystack); return in_array($value, $haystack) || array_key_exists($value, $haystack);
} elseif (is_string($haystack)) { } elseif (is_string($haystack)) {
return strpos($haystack, $value) !== false; return str_contains($haystack, $value);
} }
} }
return false; return false;
@ -184,7 +184,7 @@ class Modifier
* @param mixed $value * @param mixed $value
* @return bool * @return bool
*/ */
public static function isIterable($value) public static function isIterable(mixed $value): bool
{ {
return is_array($value) || ($value instanceof \Iterator); return is_array($value) || ($value instanceof \Iterator);
} }
@ -196,7 +196,7 @@ class Modifier
* @param string $replace The replacement value that replaces found search * @param string $replace The replacement value that replaces found search
* @return mixed * @return mixed
*/ */
public static function replace($value, $search, $replace) public static function replace(string $value, string $search, string $replace): string
{ {
return str_replace($search, $replace, $value); return str_replace($search, $replace, $value);
} }
@ -207,7 +207,7 @@ class Modifier
* @param string $replacement * @param string $replacement
* @return mixed * @return mixed
*/ */
public static function ereplace($value, $pattern, $replacement) public static function ereplace(string $value, string $pattern, string $replacement): string
{ {
return preg_replace($pattern, $replacement, $value); return preg_replace($pattern, $replacement, $value);
} }
@ -217,7 +217,7 @@ class Modifier
* @param string $pattern * @param string $pattern
* @return bool * @return bool
*/ */
public static function match($string, $pattern) public static function match(string $string, string $pattern): bool
{ {
return fnmatch($pattern, $string); return fnmatch($pattern, $string);
} }
@ -227,7 +227,7 @@ class Modifier
* @param string $pattern * @param string $pattern
* @return int * @return int
*/ */
public static function ematch($string, $pattern) public static function ematch(string $string, string $pattern): int
{ {
return preg_match($pattern, $string); return preg_match($pattern, $string);
} }
@ -237,23 +237,23 @@ class Modifier
* @param string $delimiter * @param string $delimiter
* @return array * @return array
*/ */
public static function split($value, $delimiter = ",") public static function split(mixed $value, string $delimiter = ","): array
{ {
if(is_string($value)) { if(is_string($value)) {
return explode($delimiter, $value); return explode($delimiter, $value);
} elseif(is_array($value)) { } elseif(is_array($value)) {
return $value; return $value;
} else { } else {
return array(); return [];
} }
} }
/** /**
* @param $value * @param mixed $value
* @param string $pattern * @param string $pattern
* @return array * @return array
*/ */
public static function esplit($value, $pattern = '/,\s*/S') public static function esplit(mixed $value, string $pattern = '/,\s*/S'): array
{ {
if(is_string($value)) { if(is_string($value)) {
return preg_split($pattern, $value); return preg_split($pattern, $value);
@ -265,11 +265,11 @@ class Modifier
} }
/** /**
* @param $value * @param mixed $value
* @param string $glue * @param string $glue
* @return string * @return string
*/ */
public static function join($value, $glue = ",") public static function join(mixed $value, string $glue = ","): string
{ {
if(is_array($value)) { if(is_array($value)) {
return implode($glue, $value); return implode($glue, $value);
@ -281,12 +281,13 @@ class Modifier
} }
/** /**
* @param string|int $from * @param int $from
* @param string|int $to * @param int $to
* @param int $step * @param int $step
* @return RangeIterator * @return RangeIterator
*/ */
public static function range($from, $to, $step = 1) { public static function range(mixed $from, int $to, int $step = 1): RangeIterator
{
if($from instanceof RangeIterator) { if($from instanceof RangeIterator) {
return $from->setStep($to); return $from->setStep($to);
} else { } else {

View File

@ -26,9 +26,9 @@ class Render extends \ArrayObject
"macros" => [] "macros" => []
]; ];
/** /**
* @var \Closure * @var \Closure|null
*/ */
protected \Closure $_code; protected ?\Closure $_code = null;
/** /**
* Template name * Template name
* @var string * @var string
@ -38,7 +38,7 @@ class Render extends \ArrayObject
* Provider's schema * Provider's schema
* @var string|null * @var string|null
*/ */
protected ?string $_scm; protected ?string $_scm = null;
/** /**
* Basic template name * Basic template name
* @var string * @var string

View File

@ -52,77 +52,87 @@ class Template extends Render
/** /**
* @var int shared counter * @var int shared counter
*/ */
public $i = 1; public int $i = 1;
/** /**
* @var array of macros * @var array of macros
*/ */
public $macros = array(); public array $macros = [];
/** /**
* @var array of blocks * @var array of blocks
*/ */
public $blocks = array(); public array $blocks = [];
/** /**
* @var string|null * @var string|null
*/ */
public $extends; public ?string $extends;
/** /**
* @var string|null * @var string|null
*/ */
public $extended; public ?string $extended;
/** /**
* Stack of extended templates * Stack of extended templates
* @var array * @var array
*/ */
public $ext_stack = array(); public array $ext_stack = [];
public $extend_body = false; public bool $extend_body = false;
/** /**
* Parent template * Parent template
* @var Template * @var Template
*/ */
public $parent; public ?Template $parent;
/** /**
* Template PHP code * Template PHP code
* @var string * @var string
*/ */
private $_body; private string $_body = "";
private $_compile_stage = 0; private int $_compile_stage = 0;
/** /**
* Call stack * Call stack
* @var Tag[] * @var Tag[]
*/ */
private $_stack = array(); private array $_stack = [];
/** /**
* Template source * Template source
* @var string * @var string
*/ */
private $_src; private string $_src;
/** /**
* @var int * @var int
*/ */
private $_line = 1; private int $_line = 1;
private $_post = array();
/** /**
* @var bool|string * @var callable[]
*/ */
private $_ignore = false; private array $_post = [];
/**
* @var string|null
*/
private ?string $_ignore = null;
private $_before = array(); /**
* @var string[]
*/
private array $_before = [];
private $_filters = array(); private array $_filters = [];
/** /**
* @var int crc32 of the template name * @var int crc32 of the template name
*/ */
private $_crc = 0; private int $_crc = 0;
/**
* @var callable[]
*/
private array $_tag_filters;
/** /**
* @param Fenom $fenom Template storage * @param Fenom $fenom Template storage
@ -142,16 +152,16 @@ class Template extends Render
* Get tag stack size * Get tag stack size
* @return int * @return int
*/ */
public function getStackSize() public function getStackSize(): int
{ {
return count($this->_stack); return count($this->_stack);
} }
/** /**
* @param string $tag * @param string $tag
* @return bool|\Fenom\Tag * @return Tag|null
*/ */
public function getParentScope($tag) public function getParentScope(string $tag): ?Tag
{ {
for ($i = count($this->_stack) - 1; $i >= 0; $i--) { for ($i = count($this->_stack) - 1; $i >= 0; $i--) {
if ($this->_stack[$i]->name == $tag) { if ($this->_stack[$i]->name == $tag) {
@ -159,7 +169,7 @@ class Template extends Render
} }
} }
return false; return null;
} }
/** /**
@ -167,8 +177,9 @@ class Template extends Render
* @param string $name * @param string $name
* @param bool $compile * @param bool $compile
* @return self * @return self
* @throws CompileException
*/ */
public function load($name, $compile = true) public function load(string $name, bool $compile = true): static
{ {
$this->_name = $name; $this->_name = $name;
$this->_crc = crc32($this->_name); $this->_crc = crc32($this->_name);
@ -193,8 +204,9 @@ class Template extends Render
* @param string $src template source * @param string $src template source
* @param bool $compile * @param bool $compile
* @return \Fenom\Template * @return \Fenom\Template
* @throws CompileException
*/ */
public function source($name, $src, $compile = true) public function source(string $name, string $src, bool $compile = true): static
{ {
$this->_name = $name; $this->_name = $name;
$this->_src = $src; $this->_src = $src;
@ -309,7 +321,8 @@ class Template extends Render
$this->_compile_stage = self::COMPILE_STAGE_POST_FILTERED; $this->_compile_stage = self::COMPILE_STAGE_POST_FILTERED;
} }
public function isStageDone($stage_no) { public function isStageDone(int $stage_no): bool
{
return $this->_compile_stage >= $stage_no; return $this->_compile_stage >= $stage_no;
} }
@ -318,7 +331,7 @@ class Template extends Render
* @param int $option * @param int $option
* @param bool $value * @param bool $value
*/ */
public function setOption($option, $value) public function setOption(int $option, bool $value)
{ {
if ($value) { if ($value) {
$this->_options |= $option; $this->_options |= $option;
@ -329,21 +342,21 @@ class Template extends Render
/** /**
* Execute some code at loading cache * Execute some code at loading cache
* @param $code * @param string $code
* @return void * @return void
*/ */
public function before($code) public function before(string $code): void
{ {
$this->_before[] = $code; $this->_before[] = $code;
} }
/** /**
* Generate name of temporary internal template variable (may be random) * Generate name of temporary internal template variable (maybe random)
* @return string * @return string
*/ */
public function tmpVar() public function tmpVar(): string
{ {
return sprintf('$t%x_%x', $this->_crc ? $this->_crc : mt_rand(0, 0x7FFFFFFF), $this->i++); return sprintf('$t%x_%x', $this->_crc ?: mt_rand(0, 0x7FFFFFFF), $this->i++);
} }
/** /**
@ -351,12 +364,12 @@ class Template extends Render
* *
* @param string $text * @param string $text
*/ */
private function _appendText($text) private function _appendText(string $text)
{ {
$this->_line += substr_count($text, "\n"); $this->_line += substr_count($text, "\n");
$strip = $this->_options & Fenom::AUTO_STRIP; $strip = $this->_options & Fenom::AUTO_STRIP;
if ($this->_filters) { if ($this->_filters) {
if (strpos($text, "<?") === false) { if (!str_contains($text, "<?")) {
foreach ($this->_filters as $filter) { foreach ($this->_filters as $filter) {
$text = call_user_func($filter, $this, $text); $text = call_user_func($filter, $this, $text);
} }
@ -385,9 +398,9 @@ class Template extends Render
* Append PHP code to template body * Append PHP code to template body
* *
* @param string $code * @param string $code
* @param $source * @param string $source
*/ */
private function _appendCode($code, $source) private function _appendCode(string $code, string $source)
{ {
if (!$code) { if (!$code) {
return; return;
@ -398,17 +411,17 @@ class Template extends Render
} }
/** /**
* @param $tag_name * @param string $tag_name
*/ */
public function ignore($tag_name) public function ignore(string $tag_name)
{ {
$this->_ignore = $tag_name; $this->_ignore = $tag_name;
} }
/** /**
* @param callable[] $cb * @param callable $cb
*/ */
public function addPostCompile($cb) public function addPostCompile(callable $cb)
{ {
$this->_post[] = $cb; $this->_post[] = $cb;
} }
@ -418,7 +431,7 @@ class Template extends Render
* *
* @return string * @return string
*/ */
public function getBody() public function getBody(): string
{ {
return $this->_body; return $this->_body;
} }
@ -428,7 +441,7 @@ class Template extends Render
* *
* @return string * @return string
*/ */
public function getTemplateCode() public function getTemplateCode(): string
{ {
$before = $this->_before ? implode("\n", $this->_before) . "\n" : ""; $before = $this->_before ? implode("\n", $this->_before) . "\n" : "";
return "<?php \n" . return "<?php \n" .
@ -449,7 +462,7 @@ class Template extends Render
* Make array with macros code * Make array with macros code
* @return string * @return string
*/ */
private function _getMacrosArray() private function _getMacrosArray(): string
{ {
if ($this->macros) { if ($this->macros) {
$macros = array(); $macros = array();
@ -468,7 +481,7 @@ class Template extends Render
* Return closure code * Return closure code
* @return string * @return string
*/ */
private function _getClosureSource() private function _getClosureSource(): string
{ {
return "function (\$var, \$tpl) {\n?>{$this->_body}<?php\n}"; return "function (\$var, \$tpl) {\n?>{$this->_body}<?php\n}";
} }
@ -478,11 +491,11 @@ class Template extends Render
* *
* @param array $values input values * @param array $values input values
* @throws CompileException * @throws CompileException
* @return Render * @return array
*/ */
public function display(array $values) public function display(array $values): array
{ {
if (!$this->_code) { if (!$this->_code) { // TODO: remove
// evaluate template's code // evaluate template's code
eval("\$this->_code = " . $this->_getClosureSource() . ";\n\$this->_macros = " . $this->_getMacrosArray() . ';'); eval("\$this->_code = " . $this->_getClosureSource() . ";\n\$this->_macros = " . $this->_getMacrosArray() . ';');
if (!$this->_code) { if (!$this->_code) {
@ -506,10 +519,10 @@ class Template extends Render
* Output the value * Output the value
* *
* @param string $data * @param string $data
* @param null|bool $escape * @param bool|null $escape
* @return string * @return string
*/ */
public function out($data, $escape = null) public function out(string $data, ?bool $escape = null): string
{ {
if ($escape === null) { if ($escape === null) {
$escape = $this->_options & Fenom::AUTO_ESCAPE; $escape = $this->_options & Fenom::AUTO_ESCAPE;
@ -524,8 +537,9 @@ class Template extends Render
/** /**
* Import block from another template * Import block from another template
* @param string $tpl * @param string $tpl
* @throws CompileException
*/ */
public function importBlocks($tpl) public function importBlocks(string $tpl)
{ {
$donor = $this->_fenom->compile($tpl, false); $donor = $this->_fenom->compile($tpl, false);
foreach ($donor->blocks as $name => $block) { foreach ($donor->blocks as $name => $block) {
@ -541,8 +555,9 @@ class Template extends Render
* Extends the template * Extends the template
* @param string $tpl * @param string $tpl
* @return \Fenom\Template parent * @return \Fenom\Template parent
* @throws CompileException
*/ */
public function extend($tpl) public function extend(string $tpl): Template
{ {
if (!$this->isStageDone(self::COMPILE_STAGE_PARSED)) { if (!$this->isStageDone(self::COMPILE_STAGE_PARSED)) {
$this->compile(); $this->compile();
@ -573,7 +588,7 @@ class Template extends Render
* @throws CompileException * @throws CompileException
* @return string executable PHP code * @return string executable PHP code
*/ */
public function parseTag(Tokenizer $tokens) public function parseTag(Tokenizer $tokens): string
{ {
try { try {
if ($tokens->is(Tokenizer::MACRO_STRING)) { if ($tokens->is(Tokenizer::MACRO_STRING)) {
@ -601,7 +616,7 @@ class Template extends Render
* @return string * @return string
* @throws TokenizeException * @throws TokenizeException
*/ */
public function parseEndTag(Tokenizer $tokens) public function parseEndTag(Tokenizer $tokens): string
{ {
$name = $tokens->getNext(Tokenizer::MACRO_STRING); $name = $tokens->getNext(Tokenizer::MACRO_STRING);
$tokens->next(); $tokens->next();
@ -626,12 +641,12 @@ class Template extends Render
* @throws Error\TokenizeException * @throws Error\TokenizeException
* @return string * @return string
*/ */
public function parseAct(Tokenizer $tokens) public function parseAct(Tokenizer $tokens): string
{ {
$action = $tokens->get(Tokenizer::MACRO_STRING); $action = $tokens->get(Tokenizer::MACRO_STRING);
$tokens->next(); $tokens->next();
if ($tokens->is("(", T_DOUBLE_COLON, T_NS_SEPARATOR) && !$tokens->isWhiteSpaced() if ($tokens->is("(", T_DOUBLE_COLON, T_NS_SEPARATOR) && !$tokens->isWhiteSpaced()) {
) { // just invoke function or static method // just invoke function or static method
$tokens->back(); $tokens->back();
return $this->out($this->parseExpr($tokens)); return $this->out($this->parseExpr($tokens));
} elseif ($tokens->is('.')) { } elseif ($tokens->is('.')) {
@ -652,7 +667,7 @@ class Template extends Render
if ($tag->isClosed()) { if ($tag->isClosed()) {
$tag->restoreAll(); $tag->restoreAll();
} else { } else {
array_push($this->_stack, $tag); $this->_stack[] = $tag;
} }
return $code; return $code;
} }
@ -678,7 +693,7 @@ class Template extends Render
* Get current template line * Get current template line
* @return int * @return int
*/ */
public function getLine() public function getLine(): int
{ {
return $this->_line; return $this->_line;
} }
@ -688,10 +703,9 @@ class Template extends Render
* *
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @param bool $is_var * @param bool $is_var
* @throws \Exception
* @return string * @return string
*/ */
public function parseExpr(Tokenizer $tokens, &$is_var = false) public function parseExpr(Tokenizer $tokens, bool &$is_var = false): string
{ {
$exp = array(); $exp = array();
$var = false; // last term was: true - variable, false - mixed $var = false; // last term was: true - variable, false - mixed
@ -801,10 +815,9 @@ class Template extends Render
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @param bool $is_var is parsed term - plain variable * @param bool $is_var is parsed term - plain variable
* @param int $allows * @param int $allows
* @throws \Exception * @return string
* @return bool|string
*/ */
public function parseTerm(Tokenizer $tokens, &$is_var = false, $allows = -1) public function parseTerm(Tokenizer $tokens, ?bool &$is_var = false, int $allows = -1): string
{ {
$is_var = false; $is_var = false;
if ($tokens->is(Tokenizer::MACRO_UNARY)) { if ($tokens->is(Tokenizer::MACRO_UNARY)) {
@ -941,7 +954,7 @@ class Template extends Render
* @param string $code start point (it is $var) * @param string $code start point (it is $var)
* @return string * @return string
*/ */
public function parseChain(Tokenizer $tokens, $code) public function parseChain(Tokenizer $tokens, string $code): string
{ {
do { do {
if ($tokens->is('(')) { if ($tokens->is('(')) {
@ -962,11 +975,11 @@ class Template extends Render
/** /**
* Parse variable name: $a, $a.b, $a.b['c'], $a:index * Parse variable name: $a, $a.b, $a.b['c'], $a:index
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @param $var * @param string|null $var
* @return string * @return string|null
* @throws Error\UnexpectedTokenException * @throws CompileException
*/ */
public function parseVariable(Tokenizer $tokens, $var = null) public function parseVariable(Tokenizer $tokens, ?string $var = null): ?string
{ {
if (!$var) { if (!$var) {
if ($tokens->isNext('@')) { if ($tokens->isNext('@')) {
@ -1037,7 +1050,7 @@ class Template extends Render
* @param bool $is_var * @param bool $is_var
* @return string * @return string
*/ */
public function parseAccessor(Tokenizer $tokens, &$is_var = false) public function parseAccessor(Tokenizer $tokens, bool &$is_var = false): string
{ {
$accessor = $tokens->need('$')->next()->need('.')->next()->current(); $accessor = $tokens->need('$')->next()->need('.')->next()->current();
$parser = $this->getStorage()->getAccessor($accessor); $parser = $this->getStorage()->getAccessor($accessor);
@ -1050,16 +1063,16 @@ class Template extends Render
', "callback"), ' . var_export($accessor, true) . ', $tpl, $var)'; ', "callback"), ' . var_export($accessor, true) . ', $tpl, $var)';
} else { } else {
return call_user_func_array( return call_user_func_array(
$parser['parser'], array( $parser['parser'], [
$parser['accessor'], $parser['accessor'],
$tokens->next(), $tokens->next(),
$this, $this,
&$is_var &$is_var
) ]
); );
} }
} else { } else {
return call_user_func_array($parser, array($tokens->next(), $this, &$is_var)); return call_user_func_array($parser, [$tokens->next(), $this, &$is_var]);
} }
} else { } else {
throw new \RuntimeException("Unknown accessor '\$.$accessor'"); throw new \RuntimeException("Unknown accessor '\$.$accessor'");
@ -1075,7 +1088,7 @@ class Template extends Render
* @return string * @return string
* @throws UnexpectedTokenException * @throws UnexpectedTokenException
*/ */
public function parseTernary(Tokenizer $tokens, $var, $is_var) public function parseTernary(Tokenizer $tokens, $var, $is_var): string
{ {
$empty = $tokens->is('?'); $empty = $tokens->is('?');
$tokens->next(); $tokens->next();
@ -1094,12 +1107,7 @@ class Template extends Render
return '((' . $var . ' !== null) ? ' . $var . ' : (' . $this->parseExpr($tokens) . '))'; return '((' . $var . ' !== null) ? ' . $var . ' : (' . $this->parseExpr($tokens) . '))';
} }
} }
} elseif ($tokens->is( } elseif ($tokens->is(Tokenizer::MACRO_BINARY, Tokenizer::MACRO_BOOLEAN, Tokenizer::MACRO_MATH ) || !$tokens->valid()) {
Tokenizer::MACRO_BINARY,
Tokenizer::MACRO_BOOLEAN,
Tokenizer::MACRO_MATH
) || !$tokens->valid()
) {
if ($empty) { if ($empty) {
if ($is_var) { if ($is_var) {
return '!empty(' . $var . ')'; return '!empty(' . $var . ')';
@ -1135,14 +1143,14 @@ class Template extends Render
/** /**
* Parse 'is' and 'is not' operators * Parse 'is' and 'is not' operators
* @see _tests
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @param string $value * @param string $value
* @param bool $variable * @param bool $variable
* @throws InvalidUsageException
* @return string * @return string
* @throws InvalidUsageException
* @see _tests
*/ */
public function parseIs(Tokenizer $tokens, $value, $variable = false) public function parseIs(Tokenizer $tokens, string $value, bool $variable = false): string
{ {
$tokens->next(); $tokens->next();
if ($tokens->current() == 'not') { if ($tokens->current() == 'not') {
@ -1180,11 +1188,11 @@ class Template extends Render
* Parse 'in' and 'not in' operators * Parse 'in' and 'not in' operators
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @param string $value * @param string $value
* @throws InvalidUsageException
* @throws UnexpectedTokenException
* @return string * @return string
* @throws UnexpectedTokenException
* @throws InvalidUsageException
*/ */
public function parseIn(Tokenizer $tokens, $value) public function parseIn(Tokenizer $tokens, string $value): string
{ {
$checkers = array( $checkers = array(
"string" => 'is_int(strpos(%2$s, %1$s))', "string" => 'is_int(strpos(%2$s, %1$s))',
@ -1239,7 +1247,7 @@ class Template extends Render
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @return string * @return string
*/ */
public function parseName(Tokenizer $tokens) public function parseName(Tokenizer $tokens): string
{ {
$tokens->skipIf(T_NS_SEPARATOR); $tokens->skipIf(T_NS_SEPARATOR);
$name = ""; $name = "";
@ -1260,7 +1268,7 @@ class Template extends Render
* @throws Error\UnexpectedTokenException * @throws Error\UnexpectedTokenException
* @return string * @return string
*/ */
public function parseScalar(Tokenizer $tokens) public function parseScalar(Tokenizer $tokens): string
{ {
$token = $tokens->key(); $token = $tokens->key();
switch ($token) { switch ($token) {
@ -1284,7 +1292,7 @@ class Template extends Render
* @throws UnexpectedTokenException * @throws UnexpectedTokenException
* @return string * @return string
*/ */
public function parseQuote(Tokenizer $tokens) public function parseQuote(Tokenizer $tokens): string
{ {
if ($tokens->is('"')) { if ($tokens->is('"')) {
$stop = $tokens->current(); $stop = $tokens->current();
@ -1352,7 +1360,7 @@ class Template extends Render
* @throws \Exception * @throws \Exception
* @return string * @return string
*/ */
public function parseModifier(Tokenizer $tokens, $value) public function parseModifier(Tokenizer $tokens, $value): string
{ {
while ($tokens->is("|")) { while ($tokens->is("|")) {
$modifier = $tokens->getNext(Tokenizer::MACRO_STRING); $modifier = $tokens->getNext(Tokenizer::MACRO_STRING);
@ -1392,11 +1400,11 @@ class Template extends Render
* [1, 2.3, 5+7/$var, 'string', "str {$var+3} ing", $var2, []] * [1, 2.3, 5+7/$var, 'string', "str {$var+3} ing", $var2, []]
* *
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @param int $count amount of elements * @param int $count number of elements
* @throws Error\UnexpectedTokenException
* @return string * @return string
* @throws Error\UnexpectedTokenException
*/ */
public function parseArray(Tokenizer $tokens, &$count = 0) public function parseArray(Tokenizer $tokens, int &$count = 0): string
{ {
if ($tokens->is("[")) { if ($tokens->is("[")) {
$arr = array(); $arr = array();
@ -1433,7 +1441,7 @@ class Template extends Render
* @return string * @return string
* @throws InvalidUsageException * @throws InvalidUsageException
*/ */
public function parseMacroCall(Tokenizer $tokens, $name) public function parseMacroCall(Tokenizer $tokens, $name): string
{ {
$recursive = false; $recursive = false;
$macro = false; $macro = false;
@ -1481,9 +1489,9 @@ class Template extends Render
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @throws \LogicException * @throws \LogicException
* @throws \RuntimeException * @throws \RuntimeException
* @return string * @return callable
*/ */
public function parseStatic(Tokenizer $tokens) public function parseStatic(Tokenizer $tokens): callable
{ {
if ($this->_options & Fenom::DENY_STATICS) { if ($this->_options & Fenom::DENY_STATICS) {
throw new \LogicException("Static methods are disabled"); throw new \LogicException("Static methods are disabled");
@ -1512,7 +1520,7 @@ class Template extends Render
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @return string * @return string
*/ */
public function parseArgs(Tokenizer $tokens) public function parseArgs(Tokenizer $tokens): string
{ {
$_args = "("; $_args = "(";
$tokens->next(); $tokens->next();
@ -1558,7 +1566,7 @@ class Template extends Render
* @param string $static * @param string $static
* @return mixed|string * @return mixed|string
*/ */
public function parsePlainArg(Tokenizer $tokens, &$static) public function parsePlainArg(Tokenizer $tokens, string &$static): mixed
{ {
if ($tokens->is(T_CONSTANT_ENCAPSED_STRING)) { if ($tokens->is(T_CONSTANT_ENCAPSED_STRING)) {
if ($tokens->isNext('|')) { if ($tokens->isNext('|')) {
@ -1578,10 +1586,8 @@ class Template extends Render
* Parse parameters as $key=$value * Parse parameters as $key=$value
* param1=$var param2=3 ... * param1=$var param2=3 ...
* *
* @static
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @param array $defaults * @param array|null $defaults
* @throws \Exception
* @return array * @return array
*/ */
public function parseParams(Tokenizer $tokens, array $defaults = null) public function parseParams(Tokenizer $tokens, array $defaults = null)

View File

@ -92,6 +92,7 @@ class Tokenizer
\T_INCLUDE => 1, \T_INCLUDE_ONCE => 1, \T_INSTANCEOF => 1, \T_INSTEADOF => 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_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_LOGICAL_AND => 1, \T_LOGICAL_OR => 1, \T_LOGICAL_XOR => 1, \T_METHOD_C => 1,
\T_MATCH => 1,
\T_NAMESPACE => 1, \T_NS_C => 1, \T_NEW => 1, \T_PRINT => 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_PRIVATE => 1, \T_PUBLIC => 1, \T_PROTECTED => 1, \T_REQUIRE => 1,
\T_REQUIRE_ONCE => 1, \T_RETURN => 1, \T_STRING => 1, \T_REQUIRE_ONCE => 1, \T_RETURN => 1, \T_STRING => 1,