mirror of
https://github.com/fenom-template/fenom.git
synced 2023-08-10 21:13:07 +03:00
migrate to php8
This commit is contained in:
parent
ba1bc18aba
commit
a4fbc2a6aa
@ -21,8 +21,8 @@ use Fenom\Template;
|
||||
*/
|
||||
class Fenom
|
||||
{
|
||||
const VERSION = '2.12';
|
||||
const REV = 1;
|
||||
const VERSION = '3.0';
|
||||
const REV = 2;
|
||||
/* Actions */
|
||||
const INLINE_COMPILER = 1;
|
||||
const BLOCK_COMPILER = 5;
|
||||
@ -64,18 +64,18 @@ class Fenom
|
||||
const ACCESSOR_METHOD = 'Fenom\Accessor::parserMethod';
|
||||
const ACCESSOR_CHAIN = 'Fenom\Accessor::parserChain';
|
||||
|
||||
public static $charset = "UTF-8";
|
||||
public static string $charset = "UTF-8";
|
||||
|
||||
/**
|
||||
* @var int maximum length of compiled filename (use sha1 of name if bigger)
|
||||
*/
|
||||
public static $filename_length = 200;
|
||||
public static int $filename_length = 200;
|
||||
|
||||
/**
|
||||
* @var int[] of possible options, as associative array
|
||||
* @see setOptions
|
||||
*/
|
||||
private static $_options_list = [
|
||||
private static array $_options_list = [
|
||||
"disable_accessor" => self::DENY_ACCESSOR,
|
||||
"disable_methods" => self::DENY_METHODS,
|
||||
"disable_native_funcs" => self::DENY_NATIVE_FUNCS,
|
||||
@ -94,27 +94,27 @@ class Fenom
|
||||
/**
|
||||
* @var callable[]
|
||||
*/
|
||||
public array $pre_filters = [];
|
||||
protected array $pre_filters = [];
|
||||
|
||||
/**
|
||||
* @var callable[]
|
||||
*/
|
||||
public array $filters = [];
|
||||
protected array $filters = [];
|
||||
|
||||
/**
|
||||
* @var callable[]
|
||||
*/
|
||||
public array $tag_filters = [];
|
||||
protected array $tag_filters = [];
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
public array $call_filters = [];
|
||||
protected array $call_filters = [];
|
||||
|
||||
/**
|
||||
* @var callable[]
|
||||
*/
|
||||
public array $post_filters = [];
|
||||
protected array $post_filters = [];
|
||||
|
||||
/**
|
||||
* @var Fenom\Render[] Templates storage
|
||||
@ -129,7 +129,7 @@ class Fenom
|
||||
/**
|
||||
* @var string compile prefix ID template
|
||||
*/
|
||||
protected string $_compile_id;
|
||||
protected string $_compile_id = "";
|
||||
|
||||
/**
|
||||
* @var string[] compile directory for custom provider
|
||||
@ -749,9 +749,9 @@ class Fenom
|
||||
*
|
||||
* @param string $modifier
|
||||
* @param Template|null $template
|
||||
* @return mixed
|
||||
* @return callable|null
|
||||
*/
|
||||
public function getModifier(string $modifier, Fenom\Template $template = null): string
|
||||
public function getModifier(string $modifier, Fenom\Template $template = null): ?callable
|
||||
{
|
||||
if (isset($this->_modifiers[$modifier])) {
|
||||
return $this->_modifiers[$modifier];
|
||||
@ -937,9 +937,9 @@ class Fenom
|
||||
* Get an accessor
|
||||
* @param string $name
|
||||
* @param string|null $key
|
||||
* @return callable|null
|
||||
* @return callable|array|null
|
||||
*/
|
||||
public function getAccessor(string $name,string $key = null): ?callable
|
||||
public function getAccessor(string $name,string $key = null): mixed
|
||||
{
|
||||
if(isset($this->_accessors[$name])) {
|
||||
if($key) {
|
||||
@ -998,10 +998,10 @@ class Fenom
|
||||
* @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
|
||||
* @return array
|
||||
* @throws CompileException
|
||||
*/
|
||||
public function display(string|array $template, array $vars = array()): Fenom\Render
|
||||
public function display(string|array $template, array $vars = array()): array
|
||||
{
|
||||
return $this->getTemplate($template)->display($vars);
|
||||
}
|
||||
@ -1093,12 +1093,12 @@ class Fenom
|
||||
/**
|
||||
* Load template from cache or create cache if it doesn't exists.
|
||||
*
|
||||
* @param string $template
|
||||
* @param string[]|string $template
|
||||
* @param int $opts
|
||||
* @return Fenom\Render
|
||||
* @throws CompileException
|
||||
*/
|
||||
protected function _load(string $template, int $opts): Render
|
||||
protected function _load(array|string $template, int $opts): Render
|
||||
{
|
||||
$file_name = $this->getCompileName($template, $opts);
|
||||
if (is_file($this->_compile_dir . "/" . $file_name)) {
|
||||
@ -1229,4 +1229,12 @@ class Fenom
|
||||
}
|
||||
return $mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getCallFilters(): array
|
||||
{
|
||||
return $this->call_filters;
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ class Accessor {
|
||||
if($tokens->is(T_DOUBLE_COLON)) {
|
||||
$const .= '::'.$tokens->next()->need(Tokenizer::MACRO_STRING)->getAndNext();
|
||||
}
|
||||
return '@constant('.var_export($const, true).')';
|
||||
return '(defined('.var_export($const, true).') ? constant('.var_export($const, true).') : "")';
|
||||
|
||||
}
|
||||
|
||||
@ -153,7 +153,7 @@ class Accessor {
|
||||
if($tokens->is(T_DOUBLE_COLON)) {
|
||||
$callable .= '::'.$tokens->next()->need(Tokenizer::MACRO_STRING)->getAndNext();
|
||||
}
|
||||
$call_filter = $tpl->getStorage()->call_filters;
|
||||
$call_filter = $tpl->getStorage()->getCallFilters();
|
||||
if($call_filter) {
|
||||
foreach($call_filter as $filter) {
|
||||
if(!fnmatch(addslashes($filter), $callable)) {
|
||||
|
@ -24,7 +24,6 @@ class Compiler
|
||||
/**
|
||||
* Tag {include ...}
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $tag
|
||||
* @throws \LogicException
|
||||
@ -70,6 +69,7 @@ class Compiler
|
||||
|
||||
/**
|
||||
* Tag {insert ...}
|
||||
*
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $tag
|
||||
* @return string
|
||||
@ -91,11 +91,9 @@ class Compiler
|
||||
/**
|
||||
* Open tag {if ...}
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function ifOpen(Tokenizer $tokens, Tag $scope): string
|
||||
{
|
||||
@ -106,13 +104,12 @@ class Compiler
|
||||
/**
|
||||
* Tag {elseif ...}
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $scope
|
||||
* @throws InvalidUsageException
|
||||
* @return string
|
||||
*/
|
||||
public static function tagElseIf(Tokenizer $tokens, Tag $scope)
|
||||
public static function tagElseIf(Tokenizer $tokens, Tag $scope): string
|
||||
{
|
||||
if ($scope["else"]) {
|
||||
throw new InvalidUsageException('Incorrect use of the tag {elseif}');
|
||||
@ -127,7 +124,7 @@ class Compiler
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function tagElse($tokens, Tag $scope)
|
||||
public static function tagElse(Tokenizer $tokens, Tag $scope): string
|
||||
{
|
||||
$scope["else"] = true;
|
||||
return '} else {';
|
||||
@ -136,14 +133,14 @@ class Compiler
|
||||
/**
|
||||
* Open tag {foreach ...}
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $scope
|
||||
* @throws UnexpectedTokenException
|
||||
* @throws InvalidUsageException
|
||||
* @return string
|
||||
* @throws InvalidUsageException*@throws CompileException
|
||||
* @throws UnexpectedTokenException
|
||||
* @throws CompileException
|
||||
*/
|
||||
public static function foreachOpen(Tokenizer $tokens, Tag $scope)
|
||||
public static function foreachOpen(Tokenizer $tokens, Tag $scope): string
|
||||
{
|
||||
$scope["else"] = false;
|
||||
$scope["key"] = null;
|
||||
@ -201,7 +198,7 @@ class Compiler
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function foreachElse($tokens, Tag $scope)
|
||||
public static function foreachElse(Tokenizer $tokens, Tag $scope): string
|
||||
{
|
||||
$scope["no-break"] = $scope["no-continue"] = $scope["else"] = true;
|
||||
$after = $scope["after"] ? implode("; ", $scope["after"]) . ";" : "";
|
||||
@ -214,7 +211,8 @@ class Compiler
|
||||
* @return string
|
||||
* @throws CompileException
|
||||
*/
|
||||
public static function foreachProp(Tag $scope, $prop) {
|
||||
public static function foreachProp(Tag $scope, string $prop): string
|
||||
{
|
||||
if(empty($scope["props"][$prop])) {
|
||||
$var_name = $scope["props"][$prop] = $scope->tpl->tmpVar()."_".$prop;
|
||||
switch($prop) {
|
||||
@ -248,7 +246,7 @@ class Compiler
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function foreachClose($tokens, Tag $scope)
|
||||
public static function foreachClose(Tokenizer $tokens, Tag $scope): string
|
||||
{
|
||||
$before = $scope["before"] ? implode("; ", $scope["before"]) . ";" : "";
|
||||
$head = $scope["body"] ? implode("; ", $scope["body"]) . ";" : "";
|
||||
@ -268,119 +266,11 @@ class Compiler
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $scope
|
||||
* @throws Error\UnexpectedTokenException
|
||||
* @throws Error\InvalidUsageException
|
||||
* @return string
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public static function forOpen(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
trigger_error("Fenom: tag {for} deprecated, use {foreach 1..4 as \$value} (in {$scope->tpl->getName()}:{$scope->line})", E_USER_DEPRECATED);
|
||||
$p = array(
|
||||
"index" => false,
|
||||
"first" => false,
|
||||
"last" => false,
|
||||
"step" => 1,
|
||||
"to" => false,
|
||||
// "max" => false,
|
||||
// "min" => false
|
||||
);
|
||||
$scope["after"] = $before = $body = array();
|
||||
$i = array('', '');
|
||||
$c = "";
|
||||
$var = $scope->tpl->parseTerm($tokens, $is_var);
|
||||
if (!$is_var) {
|
||||
throw new UnexpectedTokenException($tokens);
|
||||
}
|
||||
$tokens->get("=");
|
||||
$tokens->next();
|
||||
$val = $scope->tpl->parseExpr($tokens);
|
||||
$p = $scope->tpl->parseParams($tokens, $p);
|
||||
|
||||
if (is_numeric($p["step"])) {
|
||||
if ($p["step"] > 0) {
|
||||
$condition = "$var <= {$p['to']}";
|
||||
if ($p["last"]) {
|
||||
$c = "($var + {$p['step']}) > {$p['to']}";
|
||||
}
|
||||
} elseif ($p["step"] < 0) {
|
||||
$condition = "$var >= {$p['to']}";
|
||||
if ($p["last"]) {
|
||||
$c = "($var + {$p['step']}) < {$p['to']}";
|
||||
}
|
||||
} else {
|
||||
throw new InvalidUsageException("Invalid step value");
|
||||
}
|
||||
} else {
|
||||
$condition = "({$p['step']} > 0 && $var <= {$p['to']} || {$p['step']} < 0 && $var >= {$p['to']})";
|
||||
if ($p["last"]) {
|
||||
$c = "({$p['step']} > 0 && ($var + {$p['step']}) <= {$p['to']} || {$p['step']} < 0 && ($var + {$p['step']}) >= {$p['to']})";
|
||||
}
|
||||
}
|
||||
|
||||
if ($p["first"]) {
|
||||
$before[] = $p["first"] . ' = true';
|
||||
$scope["after"][] = $p["first"] . ' && (' . $p["first"] . ' = false )';
|
||||
}
|
||||
if ($p["last"]) {
|
||||
$before[] = $p["last"] . ' = false';
|
||||
$body[] = "if($c) {$p['last']} = true";
|
||||
}
|
||||
|
||||
if ($p["index"]) {
|
||||
$i[0] .= $p["index"] . ' = 0,';
|
||||
$i[1] .= $p["index"] . '++,';
|
||||
}
|
||||
|
||||
$scope["else"] = false;
|
||||
$scope["else_cond"] = "$var==$val";
|
||||
$before = $before ? implode("; ", $before) . ";" : "";
|
||||
$body = $body ? implode("; ", $body) . ";" : "";
|
||||
$scope["after"] = $scope["after"] ? implode("; ", $scope["after"]) . ";" : "";
|
||||
|
||||
return "$before for({$i[0]} $var=$val; $condition;{$i[1]} $var+={$p['step']}) { $body";
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public static function forElse($tokens, Tag $scope)
|
||||
{
|
||||
$scope["no-break"] = $scope["no-continue"] = true;
|
||||
$scope["else"] = true;
|
||||
return " } if({$scope['else_cond']}) {";
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public static function forClose($tokens, Tag $scope)
|
||||
{
|
||||
if ($scope["else"]) {
|
||||
return '}';
|
||||
} else {
|
||||
return " {$scope['after']} }";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function whileOpen(Tokenizer $tokens, Tag $scope)
|
||||
public static function whileOpen(Tokenizer $tokens, Tag $scope): string
|
||||
{
|
||||
return 'while(' . $scope->tpl->parseExpr($tokens) . ') {';
|
||||
}
|
||||
@ -388,12 +278,11 @@ class Compiler
|
||||
/**
|
||||
* Open tag {switch}
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function switchOpen(Tokenizer $tokens, Tag $scope)
|
||||
public static function switchOpen(Tokenizer $tokens, Tag $scope): string
|
||||
{
|
||||
$expr = $scope->tpl->parseExpr($tokens);
|
||||
$scope["case"] = array();
|
||||
@ -409,7 +298,7 @@ class Compiler
|
||||
* Resort cases for {switch}
|
||||
* @param Tag $scope
|
||||
*/
|
||||
private static function _caseResort(Tag $scope)
|
||||
private static function _caseResort(Tag $scope): void
|
||||
{
|
||||
$content = $scope->cutContent();
|
||||
foreach ($scope["last"] as $case) {
|
||||
@ -428,12 +317,11 @@ class Compiler
|
||||
/**
|
||||
* Tag {case ...}
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $tag
|
||||
* @return string
|
||||
*/
|
||||
public static function tagCase(Tokenizer $tokens, Tag $tag)
|
||||
public static function tagCase(Tokenizer $tokens, Tag $tag): string
|
||||
{
|
||||
self::_caseResort($tag);
|
||||
do {
|
||||
@ -456,12 +344,11 @@ class Compiler
|
||||
/**
|
||||
* Tag {default}
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function tagDefault($tokens, Tag $scope)
|
||||
public static function tagDefault(Tokenizer $tokens, Tag $scope): string
|
||||
{
|
||||
self::_caseResort($scope);
|
||||
$scope["last"][] = false;
|
||||
@ -471,12 +358,11 @@ class Compiler
|
||||
/**
|
||||
* Close tag {switch}
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function switchClose($tokens, Tag $scope)
|
||||
public static function switchClose(Tokenizer $tokens, Tag $scope): string
|
||||
{
|
||||
self::_caseResort($scope);
|
||||
$expr = $scope["var"];
|
||||
@ -495,13 +381,12 @@ class Compiler
|
||||
/**
|
||||
* Tag {continue}
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $scope
|
||||
* @throws InvalidUsageException
|
||||
* @return string
|
||||
* @throws InvalidUsageException
|
||||
*/
|
||||
public static function tagContinue($tokens, Tag $scope)
|
||||
public static function tagContinue(Tokenizer $tokens, Tag $scope): string
|
||||
{
|
||||
if (empty($scope["no-continue"])) {
|
||||
return 'continue;';
|
||||
@ -513,13 +398,12 @@ class Compiler
|
||||
/**
|
||||
* Tag {break}
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $scope
|
||||
* @throws InvalidUsageException
|
||||
* @return string
|
||||
* @throws InvalidUsageException
|
||||
*/
|
||||
public static function tagBreak($tokens, Tag $scope)
|
||||
public static function tagBreak(Tokenizer $tokens, Tag $scope): string
|
||||
{
|
||||
if (empty($scope["no-break"])) {
|
||||
return 'break;';
|
||||
@ -530,12 +414,13 @@ class Compiler
|
||||
|
||||
/**
|
||||
* Dispatch {extends} tag
|
||||
*
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $tag
|
||||
* @throws Error\InvalidUsageException
|
||||
* @return string
|
||||
*/
|
||||
public static function tagExtends(Tokenizer $tokens, Tag $tag)
|
||||
public static function tagExtends(Tokenizer $tokens, Tag $tag): void
|
||||
{
|
||||
$tpl = $tag->tpl;
|
||||
if ($tpl->extends) {
|
||||
@ -559,8 +444,9 @@ class Compiler
|
||||
* Post compile action for {extends ...} tag
|
||||
* @param Template $tpl
|
||||
* @param string $body
|
||||
* @throws CompileException
|
||||
*/
|
||||
public static function extendBody($tpl, &$body)
|
||||
public static function extendBody(Template $tpl, string &$body): void
|
||||
{
|
||||
if ($tpl->dynamic_extends) {
|
||||
if (!$tpl->ext_stack) {
|
||||
@ -586,10 +472,9 @@ class Compiler
|
||||
* Tag {use ...}
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $tag
|
||||
* @throws Error\InvalidUsageException
|
||||
* @return string
|
||||
* @throws Error\InvalidUsageException|CompileException
|
||||
*/
|
||||
public static function tagUse(Tokenizer $tokens, Tag $tag)
|
||||
public static function tagUse(Tokenizer $tokens, Tag $tag): void
|
||||
{
|
||||
$tpl = $tag->tpl;
|
||||
if ($tpl->getStackSize()) {
|
||||
@ -608,9 +493,8 @@ class Compiler
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $scope
|
||||
* @throws \RuntimeException
|
||||
* @return string
|
||||
*/
|
||||
public static function tagBlockOpen(Tokenizer $tokens, Tag $scope)
|
||||
public static function tagBlockOpen(Tokenizer $tokens, Tag $scope): void
|
||||
{
|
||||
$scope["cname"] = $scope->tpl->parsePlainArg($tokens, $name);
|
||||
if (!$name) {
|
||||
@ -624,7 +508,7 @@ class Compiler
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $scope
|
||||
*/
|
||||
public static function tagBlockClose($tokens, Tag $scope)
|
||||
public static function tagBlockClose(Tokenizer $tokens, Tag $scope): void
|
||||
{
|
||||
$tpl = $scope->tpl;
|
||||
$name = $scope["name"];
|
||||
@ -658,7 +542,7 @@ class Compiler
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function tagParent($tokens, Tag $scope)
|
||||
public static function tagParent(Tokenizer $tokens, Tag $scope): string
|
||||
{
|
||||
$block_scope = $scope->tpl->getParentScope('block');
|
||||
if (!$block_scope['use_parent']) {
|
||||
@ -672,7 +556,7 @@ class Compiler
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function stdClose()
|
||||
public static function stdClose(): string
|
||||
{
|
||||
return '}';
|
||||
}
|
||||
@ -684,7 +568,7 @@ class Compiler
|
||||
* @param Tag $tag
|
||||
* @return string
|
||||
*/
|
||||
public static function stdFuncParser(Tokenizer $tokens, Tag $tag)
|
||||
public static function stdFuncParser(Tokenizer $tokens, Tag $tag): string
|
||||
{
|
||||
if(is_string($tag->callback)) {
|
||||
return $tag->out($tag->callback . "(" . self::toArray($tag->tpl->parseParams($tokens)) . ', $tpl, $var)');
|
||||
@ -700,8 +584,9 @@ class Compiler
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $tag
|
||||
* @return string
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public static function smartFuncParser(Tokenizer $tokens, Tag $tag)
|
||||
public static function smartFuncParser(Tokenizer $tokens, Tag $tag): string
|
||||
{
|
||||
if (strpos($tag->callback, "::") || is_array($tag->callback)) {
|
||||
list($class, $method) = explode("::", $tag->callback, 2);
|
||||
@ -730,7 +615,7 @@ class Compiler
|
||||
* @param Tag $tag
|
||||
* @return string
|
||||
*/
|
||||
public static function stdFuncOpen(Tokenizer $tokens, Tag $tag)
|
||||
public static function stdFuncOpen(Tokenizer $tokens, Tag $tag): string
|
||||
{
|
||||
$tag["params"] = self::toArray($tag->tpl->parseParams($tokens));
|
||||
$tag->setOption(\Fenom::AUTO_ESCAPE, false);
|
||||
@ -744,7 +629,7 @@ class Compiler
|
||||
* @param Tag $tag
|
||||
* @return string
|
||||
*/
|
||||
public static function stdFuncClose($tokens, Tag $tag)
|
||||
public static function stdFuncClose(Tokenizer $tokens, Tag $tag): string
|
||||
{
|
||||
$tag->restore(\Fenom::AUTO_ESCAPE);
|
||||
if(is_string($tag->callback)) {
|
||||
@ -757,10 +642,10 @@ class Compiler
|
||||
|
||||
/**
|
||||
* Convert array of code to string array
|
||||
* @param $params
|
||||
* @param array $params
|
||||
* @return string
|
||||
*/
|
||||
public static function toArray($params)
|
||||
public static function toArray(array $params): string
|
||||
{
|
||||
$_code = array();
|
||||
foreach ($params as $k => $v) {
|
||||
@ -774,8 +659,9 @@ class Compiler
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
* @throws CompileException
|
||||
*/
|
||||
public static function setOpen(Tokenizer $tokens, Tag $scope)
|
||||
public static function setOpen(Tokenizer $tokens, Tag $scope): string
|
||||
{
|
||||
if($tokens->is(T_VARIABLE)) {
|
||||
$var = $scope->tpl->parseVariable($tokens);
|
||||
@ -820,12 +706,12 @@ class Compiler
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function setClose($tokens, Tag $scope)
|
||||
public static function setClose(Tokenizer $tokens, Tag $scope): string
|
||||
{
|
||||
return $scope["name"] . '=' . $scope["value"] . ';';
|
||||
}
|
||||
|
||||
public static function tagDo($tokens, Tag $scope)
|
||||
public static function tagDo(Tokenizer $tokens, Tag $scope): string
|
||||
{
|
||||
return $scope->tpl->parseExpr($tokens).';';
|
||||
}
|
||||
@ -835,19 +721,20 @@ class Compiler
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
* @throws CompileException
|
||||
*/
|
||||
public static function filterOpen($tokens, Tag $scope)
|
||||
public static function filterOpen(Tokenizer $tokens, Tag $scope): string
|
||||
{
|
||||
$scope["filter"] = $scope->tpl->parseModifier($tokens, "ob_get_clean()");
|
||||
return "ob_start();";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $tokens
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function filterClose($tokens, Tag $scope)
|
||||
public static function filterClose(Tokenizer $tokens, Tag $scope): string
|
||||
{
|
||||
return "echo " . $scope["filter"] . ";";
|
||||
}
|
||||
@ -860,7 +747,7 @@ class Compiler
|
||||
* @throws Error\InvalidUsageException
|
||||
* @return string
|
||||
*/
|
||||
public static function tagCycle(Tokenizer $tokens, Tag $tag)
|
||||
public static function tagCycle(Tokenizer $tokens, Tag $tag): string
|
||||
{
|
||||
$tpl = $tag->tpl;
|
||||
if ($tokens->is("[")) {
|
||||
@ -883,11 +770,11 @@ class Compiler
|
||||
|
||||
/**
|
||||
* Runtime cycle callback
|
||||
* @param mixed $vals
|
||||
* @param $index
|
||||
* @param array $vals
|
||||
* @param int $index
|
||||
* @return mixed
|
||||
*/
|
||||
public static function cycle($vals, $index)
|
||||
public static function cycle(array $vals, int $index): mixed
|
||||
{
|
||||
return $vals[$index % count($vals)];
|
||||
}
|
||||
@ -897,11 +784,11 @@ class Compiler
|
||||
*
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $tag
|
||||
* @throws Error\UnexpectedTokenException
|
||||
* @throws Error\InvalidUsageException
|
||||
* @return string
|
||||
* @throws Error\InvalidUsageException|CompileException
|
||||
* @throws Error\UnexpectedTokenException
|
||||
*/
|
||||
public static function tagImport(Tokenizer $tokens, Tag $tag)
|
||||
public static function tagImport(Tokenizer $tokens, Tag $tag): string
|
||||
{
|
||||
$tpl = $tag->tpl;
|
||||
$import = array();
|
||||
@ -966,7 +853,7 @@ class Compiler
|
||||
* @param Tag $scope
|
||||
* @throws InvalidUsageException
|
||||
*/
|
||||
public static function macroOpen(Tokenizer $tokens, Tag $scope)
|
||||
public static function macroOpen(Tokenizer $tokens, Tag $scope): void
|
||||
{
|
||||
$scope["name"] = $tokens->get(Tokenizer::MACRO_STRING);
|
||||
$scope["recursive"] = false;
|
||||
@ -1011,7 +898,7 @@ class Compiler
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $scope
|
||||
*/
|
||||
public static function macroClose($tokens, Tag $scope)
|
||||
public static function macroClose(Tokenizer $tokens, Tag $scope): void
|
||||
{
|
||||
if ($scope["recursive"]) {
|
||||
$scope["macro"]["recursive"] = true;
|
||||
@ -1027,7 +914,7 @@ class Compiler
|
||||
* @param Tag $tag
|
||||
* @return string
|
||||
*/
|
||||
public static function tagRaw(Tokenizer $tokens, Tag $tag)
|
||||
public static function tagRaw(Tokenizer $tokens, Tag $tag): string
|
||||
{
|
||||
return 'echo ' . $tag->tpl->parseExpr($tokens);
|
||||
}
|
||||
@ -1036,9 +923,9 @@ class Compiler
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $tag
|
||||
*/
|
||||
public static function escapeOpen(Tokenizer $tokens, Tag $tag)
|
||||
public static function escapeOpen(Tokenizer $tokens, Tag $tag): void
|
||||
{
|
||||
$expected = ($tokens->get(T_STRING) == "true" ? true : false);
|
||||
$expected = $tokens->get(T_STRING) == "true";
|
||||
$tokens->next();
|
||||
$tag->setOption(\Fenom::AUTO_ESCAPE, $expected);
|
||||
}
|
||||
@ -1046,7 +933,7 @@ class Compiler
|
||||
/**
|
||||
* Do nothing
|
||||
*/
|
||||
public static function nope()
|
||||
public static function nope(): void
|
||||
{
|
||||
}
|
||||
|
||||
@ -1054,30 +941,33 @@ class Compiler
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $tag
|
||||
*/
|
||||
public static function stripOpen(Tokenizer $tokens, Tag $tag)
|
||||
public static function stripOpen(Tokenizer $tokens, Tag $tag): void
|
||||
{
|
||||
$expected = ($tokens->get(T_STRING) == "true" ? true : false);
|
||||
$expected = $tokens->get(T_STRING) == "true";
|
||||
$tokens->next();
|
||||
$tag->setOption(\Fenom::AUTO_STRIP, $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag {ignore}
|
||||
*
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $tag
|
||||
*/
|
||||
public static function ignoreOpen($tokens, Tag $tag)
|
||||
public static function ignoreOpen(Tokenizer $tokens, Tag $tag): void
|
||||
{
|
||||
$tag->tpl->ignore('ignore');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag {unset ...}
|
||||
*
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $tag
|
||||
* @return string
|
||||
* @throws CompileException
|
||||
*/
|
||||
public static function tagUnset(Tokenizer $tokens, Tag $tag)
|
||||
public static function tagUnset(Tokenizer $tokens, Tag $tag): string
|
||||
{
|
||||
$unset = array();
|
||||
while($tokens->valid()) {
|
||||
@ -1086,7 +976,7 @@ class Compiler
|
||||
return 'unset('.implode(", ", $unset).')';
|
||||
}
|
||||
|
||||
public static function tagPaste(Tokenizer $tokens, Tag $tag)
|
||||
public static function tagPaste(Tokenizer $tokens, Tag $tag): string
|
||||
{
|
||||
$name = str_replace(array('\'', '"'), '', $tokens->get(T_CONSTANT_ENCAPSED_STRING));
|
||||
$tokens->next();
|
||||
|
@ -15,16 +15,16 @@ namespace Fenom;
|
||||
*/
|
||||
class Provider implements ProviderInterface
|
||||
{
|
||||
private $_path;
|
||||
private string $_path;
|
||||
|
||||
protected $_clear_cache = false;
|
||||
protected bool $_clear_cache = false;
|
||||
|
||||
/**
|
||||
* Clean directory from files
|
||||
*
|
||||
* @param string $path
|
||||
*/
|
||||
public static function clean($path)
|
||||
public static function clean(string $path)
|
||||
{
|
||||
if (is_file($path)) {
|
||||
unlink($path);
|
||||
@ -39,7 +39,7 @@ class Provider implements ProviderInterface
|
||||
foreach ($iterator as $file) {
|
||||
/* @var \splFileInfo $file */
|
||||
if ($file->isFile()) {
|
||||
if (strpos($file->getBasename(), ".") !== 0) {
|
||||
if (!str_starts_with($file->getBasename(), ".")) {
|
||||
unlink($file->getRealPath());
|
||||
}
|
||||
} elseif ($file->isDir()) {
|
||||
@ -54,7 +54,7 @@ class Provider implements ProviderInterface
|
||||
*
|
||||
* @param string $path
|
||||
*/
|
||||
public static function rm($path)
|
||||
public static function rm(string $path)
|
||||
{
|
||||
self::clean($path);
|
||||
if (is_dir($path)) {
|
||||
@ -64,9 +64,9 @@ class Provider implements ProviderInterface
|
||||
|
||||
/**
|
||||
* @param string $template_dir directory of templates
|
||||
* @throws \LogicException if directory doesn't exists
|
||||
* @throws \LogicException if directory doesn't exist
|
||||
*/
|
||||
public function __construct($template_dir)
|
||||
public function __construct(string $template_dir)
|
||||
{
|
||||
if ($_dir = realpath($template_dir)) {
|
||||
$this->_path = $_dir;
|
||||
@ -80,17 +80,17 @@ class Provider implements ProviderInterface
|
||||
* @see http://php.net/manual/en/function.clearstatcache.php
|
||||
* @param bool $status
|
||||
*/
|
||||
public function setClearCachedStats($status = true) {
|
||||
public function setClearCachedStats(bool $status = true) {
|
||||
$this->_clear_cache = $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get source and mtime of template by name
|
||||
* @param string $tpl
|
||||
* @param int $time load last modified time
|
||||
* @param float|null $time load last modified time
|
||||
* @return string
|
||||
*/
|
||||
public function getSource($tpl, &$time)
|
||||
public function getSource(string $tpl, ?float &$time): string
|
||||
{
|
||||
$tpl = $this->_getTemplatePath($tpl);
|
||||
if($this->_clear_cache) {
|
||||
@ -103,24 +103,24 @@ class Provider implements ProviderInterface
|
||||
/**
|
||||
* Get last modified of template by name
|
||||
* @param string $tpl
|
||||
* @return int
|
||||
* @return float
|
||||
*/
|
||||
public function getLastModified($tpl)
|
||||
public function getLastModified(string $tpl): float
|
||||
{
|
||||
$tpl = $this->_getTemplatePath($tpl);
|
||||
if($this->_clear_cache) {
|
||||
clearstatcache(true, $tpl);
|
||||
}
|
||||
return filemtime($tpl);
|
||||
return (float)filemtime($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all names of templates from provider.
|
||||
*
|
||||
* @param string $extension all templates must have this extension, default .tpl
|
||||
* @return array|\Iterator
|
||||
* @return iterable
|
||||
*/
|
||||
public function getList($extension = "tpl")
|
||||
public function getList(string $extension = "tpl"): iterable
|
||||
{
|
||||
$list = array();
|
||||
$iterator = new \RecursiveIteratorIterator(
|
||||
@ -140,14 +140,14 @@ class Provider implements ProviderInterface
|
||||
|
||||
/**
|
||||
* Get template path
|
||||
* @param $tpl
|
||||
* @param string $tpl
|
||||
* @return string
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function _getTemplatePath($tpl)
|
||||
protected function _getTemplatePath(string $tpl): string
|
||||
{
|
||||
$path = realpath($this->_path . "/" . $tpl);
|
||||
if ($path && strpos($path, $this->_path) === 0) {
|
||||
if ($path && str_starts_with($path, $this->_path)) {
|
||||
return $path;
|
||||
} else {
|
||||
throw new \RuntimeException("Template $tpl not found");
|
||||
@ -158,9 +158,9 @@ class Provider implements ProviderInterface
|
||||
* @param string $tpl
|
||||
* @return bool
|
||||
*/
|
||||
public function templateExists($tpl)
|
||||
public function templateExists(string $tpl): bool
|
||||
{
|
||||
return ($path = realpath($this->_path . "/" . $tpl)) && strpos($path, $this->_path) === 0;
|
||||
return ($path = realpath($this->_path . "/" . $tpl)) && str_starts_with($path, $this->_path);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -169,7 +169,7 @@ class Provider implements ProviderInterface
|
||||
* @param array $templates [template_name => modified, ...] By conversation, you may trust the template's name
|
||||
* @return bool
|
||||
*/
|
||||
public function verify(array $templates)
|
||||
public function verify(array $templates): bool
|
||||
{
|
||||
foreach ($templates as $template => $mtime) {
|
||||
$template = $this->_path . '/' . $template;
|
||||
|
@ -20,20 +20,20 @@ interface ProviderInterface
|
||||
* @param string $tpl
|
||||
* @return bool
|
||||
*/
|
||||
public function templateExists($tpl);
|
||||
public function templateExists(string $tpl): bool;
|
||||
|
||||
/**
|
||||
* @param string $tpl
|
||||
* @param int $time
|
||||
* @param float $time seconds with micro
|
||||
* @return string
|
||||
*/
|
||||
public function getSource($tpl, &$time);
|
||||
public function getSource(string $tpl, float &$time): string;
|
||||
|
||||
/**
|
||||
* @param string $tpl
|
||||
* @return int
|
||||
* @return float seconds with micro
|
||||
*/
|
||||
public function getLastModified($tpl);
|
||||
public function getLastModified(string $tpl): float;
|
||||
|
||||
/**
|
||||
* Verify templates (check mtime)
|
||||
@ -41,11 +41,11 @@ interface ProviderInterface
|
||||
* @param array $templates [template_name => modified, ...] By conversation, you may trust the template's name
|
||||
* @return bool if true - all templates are valid else some templates are invalid
|
||||
*/
|
||||
public function verify(array $templates);
|
||||
public function verify(array $templates): bool;
|
||||
|
||||
/**
|
||||
* Get all names of template from provider
|
||||
* @return array|\Iterator
|
||||
* @return iterable
|
||||
*/
|
||||
public function getList();
|
||||
public function getList(): iterable;
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ class RangeIterator implements Iterator, Countable
|
||||
public int $max;
|
||||
public int $step;
|
||||
|
||||
public function __construct($min, $max, $step = 1)
|
||||
public function __construct(int $min, int $max, int $step = 1)
|
||||
{
|
||||
$this->min = $min;
|
||||
$this->max = $max;
|
||||
@ -42,7 +42,7 @@ class RangeIterator implements Iterator, Countable
|
||||
/**
|
||||
* Return the current element
|
||||
*/
|
||||
public function current(): int
|
||||
public function current(): mixed
|
||||
{
|
||||
return $this->current;
|
||||
}
|
||||
@ -50,7 +50,7 @@ class RangeIterator implements Iterator, Countable
|
||||
/**
|
||||
* Move forward to next element
|
||||
*/
|
||||
public function next()
|
||||
public function next(): void
|
||||
{
|
||||
$this->current += $this->step;
|
||||
$this->index++;
|
||||
@ -58,9 +58,9 @@ class RangeIterator implements Iterator, Countable
|
||||
|
||||
/**
|
||||
* Return the key of the current element
|
||||
* @return int
|
||||
* @return mixed
|
||||
*/
|
||||
public function key(): int
|
||||
public function key(): mixed
|
||||
{
|
||||
return $this->index;
|
||||
}
|
||||
@ -77,7 +77,7 @@ class RangeIterator implements Iterator, Countable
|
||||
/**
|
||||
* Rewind the Iterator to the first element
|
||||
*/
|
||||
public function rewind()
|
||||
public function rewind(): void
|
||||
{
|
||||
if($this->step > 0) {
|
||||
$this->current = min($this->min, $this->max);
|
||||
|
@ -205,7 +205,7 @@ class Tag extends \ArrayObject
|
||||
}
|
||||
$code = call_user_func($this->_close, $tokenizer, $this);
|
||||
$this->restoreAll();
|
||||
return $code;
|
||||
return (string)$code;
|
||||
} else {
|
||||
throw new \LogicException("Can not use a inline tag {$this->name} as a block");
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ class Template extends Render
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
public ?string $extends;
|
||||
public ?string $extends = null;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
@ -80,6 +80,7 @@ class Template extends Render
|
||||
public array $ext_stack = [];
|
||||
|
||||
public bool $extend_body = false;
|
||||
public string $dynamic_extends = "";
|
||||
|
||||
/**
|
||||
* Parent template
|
||||
@ -483,7 +484,7 @@ class Template extends Render
|
||||
*/
|
||||
private function _getClosureSource(): string
|
||||
{
|
||||
return "function (\$var, \$tpl) {\n?>{$this->_body}<?php\n}";
|
||||
return "function (mixed \$var, mixed \$tpl) {\n?>{$this->_body}<?php\n}";
|
||||
}
|
||||
|
||||
/**
|
||||
@ -669,7 +670,7 @@ class Template extends Render
|
||||
} else {
|
||||
$this->_stack[] = $tag;
|
||||
}
|
||||
return $code;
|
||||
return (string)$code;
|
||||
}
|
||||
|
||||
for ($j = $i = count($this->_stack) - 1; $i >= 0; $i--) { // call function's internal tag
|
||||
@ -705,7 +706,7 @@ class Template extends Render
|
||||
* @param bool $is_var
|
||||
* @return string
|
||||
*/
|
||||
public function parseExpr(Tokenizer $tokens, bool &$is_var = false): string
|
||||
public function parseExpr(Tokenizer $tokens, ?bool &$is_var = false): string
|
||||
{
|
||||
$exp = array();
|
||||
$var = false; // last term was: true - variable, false - mixed
|
||||
@ -714,7 +715,7 @@ class Template extends Render
|
||||
while ($tokens->valid()) {
|
||||
// parse term
|
||||
$term = $this->parseTerm($tokens, $var, -1); // term of the expression
|
||||
if ($term !== false) {
|
||||
if ($term !== "") {
|
||||
if ($tokens->is('?', '!')) {
|
||||
if ($cond) {
|
||||
$term = array_pop($exp) . ' ' . $term;
|
||||
@ -910,7 +911,7 @@ class Template extends Render
|
||||
$args = $this->parseArgs($tokens);
|
||||
$code = $unary . $this->parseChain($tokens, $method . $args);
|
||||
} else {
|
||||
return false;
|
||||
return "";
|
||||
}
|
||||
break;
|
||||
case T_ISSET:
|
||||
@ -933,7 +934,7 @@ class Template extends Render
|
||||
if ($unary) {
|
||||
throw new UnexpectedTokenException($tokens->back());
|
||||
} else {
|
||||
return false;
|
||||
return "";
|
||||
}
|
||||
}
|
||||
if (($allows & self::TERM_MODS) && $tokens->is('|')) {
|
||||
@ -1050,7 +1051,7 @@ class Template extends Render
|
||||
* @param bool $is_var
|
||||
* @return string
|
||||
*/
|
||||
public function parseAccessor(Tokenizer $tokens, bool &$is_var = false): string
|
||||
public function parseAccessor(Tokenizer $tokens, ?bool &$is_var = false): string
|
||||
{
|
||||
$accessor = $tokens->need('$')->next()->need('.')->next()->current();
|
||||
$parser = $this->getStorage()->getAccessor($accessor);
|
||||
@ -1356,9 +1357,8 @@ class Template extends Render
|
||||
*
|
||||
* @param Tokenizer $tokens
|
||||
* @param $value
|
||||
* @throws \LogicException
|
||||
* @throws \Exception
|
||||
* @return string
|
||||
* @throws CompileException
|
||||
*/
|
||||
public function parseModifier(Tokenizer $tokens, $value): string
|
||||
{
|
||||
@ -1369,7 +1369,7 @@ class Template extends Render
|
||||
} else {
|
||||
$mods = $this->_fenom->getModifier($modifier, $this);
|
||||
if (!$mods) {
|
||||
throw new \Exception("Modifier " . $tokens->current() . " not found");
|
||||
throw new CompileException("Modifier " . $tokens->current() . " not found");
|
||||
}
|
||||
$tokens->next();
|
||||
}
|
||||
@ -1563,10 +1563,10 @@ class Template extends Render
|
||||
* Parse first unnamed argument
|
||||
*
|
||||
* @param Tokenizer $tokens
|
||||
* @param string $static
|
||||
* @return mixed|string
|
||||
* @param string|null $static
|
||||
* @return string
|
||||
*/
|
||||
public function parsePlainArg(Tokenizer $tokens, string &$static): mixed
|
||||
public function parsePlainArg(Tokenizer $tokens, ?string &$static = null): string
|
||||
{
|
||||
if ($tokens->is(T_CONSTANT_ENCAPSED_STRING)) {
|
||||
if ($tokens->isNext('|')) {
|
||||
|
@ -181,7 +181,7 @@ class Tokenizer
|
||||
$this->_curr = null;
|
||||
$this->_next = null;
|
||||
$this->_prev = null;
|
||||
$tokens = array(-1 => array(\T_WHITESPACE, '', '', 1));
|
||||
$tokens = [-1 => [\T_WHITESPACE, '', '', 1]];
|
||||
$_tokens = token_get_all("<?php " . $query);
|
||||
$line = 1;
|
||||
array_shift($_tokens);
|
||||
@ -191,14 +191,37 @@ class Tokenizer
|
||||
if ($token === '"' || $token === "'" || $token === "`") {
|
||||
$this->quotes++;
|
||||
}
|
||||
$token = array(
|
||||
$token = [
|
||||
$token,
|
||||
$token,
|
||||
$line,
|
||||
);
|
||||
];
|
||||
} elseif ($token[0] === \T_WHITESPACE) {
|
||||
$tokens[$i - 1][2] = $token[1];
|
||||
continue;
|
||||
} elseif ($token[0] === \T_NAME_FULLY_QUALIFIED || $token[0] === \T_NAME_QUALIFIED || $token[0] === \T_NAME_RELATIVE) {
|
||||
$parts = explode("\\", $token[1]);
|
||||
for ($k = 0; $k < count($parts); $k++) {
|
||||
if ($parts[$k] !== "") {
|
||||
$tokens[] = [
|
||||
T_STRING,
|
||||
$parts[$k],
|
||||
"",
|
||||
$line = $token[2]
|
||||
];
|
||||
$i++;
|
||||
}
|
||||
if (isset($parts[$k], $parts[$k+1])) {
|
||||
$tokens[] = [
|
||||
"\\",
|
||||
"\\",
|
||||
"",
|
||||
$line = $token[2]
|
||||
];
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
} elseif ($token[0] === \T_DNUMBER) { // fix .1 and 1.
|
||||
if(str_starts_with($token[1], '.')) {
|
||||
$tokens[] = array(
|
||||
|
@ -3,13 +3,17 @@ namespace Fenom;
|
||||
|
||||
use Fenom, Fenom\Provider as FS;
|
||||
|
||||
class CustomFenom extends Fenom {
|
||||
public mixed $prop;
|
||||
}
|
||||
|
||||
class TestCase extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public $template_path = 'template';
|
||||
/**
|
||||
* @var Fenom
|
||||
* @var CustomFenom
|
||||
*/
|
||||
public $fenom;
|
||||
public CustomFenom $fenom;
|
||||
|
||||
public $values;
|
||||
|
||||
@ -61,7 +65,7 @@ class TestCase extends \PHPUnit\Framework\TestCase
|
||||
FS::clean($this->getCompilePath());
|
||||
}
|
||||
|
||||
$this->fenom = Fenom::factory(FENOM_RESOURCES . '/' . $this->template_path, $this->getCompilePath());
|
||||
$this->fenom = CustomFenom::factory(FENOM_RESOURCES . '/' . $this->template_path, $this->getCompilePath());
|
||||
$this->fenom->addProvider('persist', new Provider(FENOM_RESOURCES . '/provider'));
|
||||
$this->fenom->addModifier('dots', __CLASS__ . '::dots');
|
||||
$this->fenom->addModifier('concat', __CLASS__ . '::concat');
|
||||
@ -168,7 +172,7 @@ class TestCase extends \PHPUnit\Framework\TestCase
|
||||
$this->fenom->setOptions($options);
|
||||
try {
|
||||
$this->fenom->compileCode($code, "inline.tpl");
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Throwable $e) {
|
||||
$this->assertSame($exception, get_class($e), "Exception $code");
|
||||
$this->assertStringStartsWith($message, $e->getMessage());
|
||||
$this->fenom->setOptions($opt);
|
||||
@ -180,7 +184,11 @@ class TestCase extends \PHPUnit\Framework\TestCase
|
||||
|
||||
public function assertRender($tpl, $result, array $vars = array(), $debug = false)
|
||||
{
|
||||
$template = $this->fenom->compileCode($tpl);
|
||||
try {
|
||||
$template = $this->fenom->compileCode($tpl);
|
||||
} catch (\Throwable $e) {
|
||||
throw new \RuntimeException("Template failed: $tpl",0 , $e);
|
||||
}
|
||||
if ($debug) {
|
||||
print_r("\nDEBUG $tpl:\n" . $template->getBody());
|
||||
}
|
||||
@ -300,7 +308,8 @@ class Helper
|
||||
|
||||
const CONSTANT = "helper.class.const";
|
||||
|
||||
public $word = 'helper';
|
||||
public string $word = 'helper';
|
||||
public Helper $self;
|
||||
|
||||
public function __construct($word)
|
||||
{
|
||||
|
@ -132,7 +132,8 @@ class AccessorTest extends TestCase
|
||||
* @group issue260
|
||||
*/
|
||||
public function testBug260() {
|
||||
$this->fenom->compileCode('{$.php.Fenom::factory()->addModifier("intval", "intval")}');
|
||||
$t = $this->fenom->compileCode('{$.php.Fenom::factory()->addModifier("intval", "intval")}');
|
||||
$this->assertInstanceOf(Template::class, $t);
|
||||
}
|
||||
|
||||
|
||||
@ -236,15 +237,28 @@ class AccessorTest extends TestCase
|
||||
$this->execError($tpl, $exception, $message);
|
||||
}
|
||||
|
||||
public function getThree() {
|
||||
public static function getThree(): int
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
public static function getThreeArray(): array
|
||||
{
|
||||
return ["three" => 3];
|
||||
}
|
||||
|
||||
public static function getThreeCb(): callable
|
||||
{
|
||||
return fn() => 3;
|
||||
}
|
||||
|
||||
public static int $three = 3;
|
||||
|
||||
public static function providerSmartAccessor() {
|
||||
return array(
|
||||
array('acc', '$tpl->getStorage()->test->values', \Fenom::ACCESSOR_VAR, '{$.acc.three}', '3'),
|
||||
array('acc', '$tpl->getStorage()->test->getThree', \Fenom::ACCESSOR_CALL, '{$.acc()}', '3'),
|
||||
array('acc', 'three', \Fenom::ACCESSOR_PROPERTY, '{$.acc}', '3'),
|
||||
array('acc', '\Fenom\AccessorTest::getThreeArray()', \Fenom::ACCESSOR_VAR, '{$.acc.three}', '3'),
|
||||
array('acc', '\Fenom\AccessorTest::getThreeCb()', \Fenom::ACCESSOR_CALL, '{$.acc()}', '3'),
|
||||
array('acc', 'prop', \Fenom::ACCESSOR_PROPERTY, '{$.acc}', 'something'),
|
||||
array('acc', 'templateExists', \Fenom::ACCESSOR_METHOD, '{$.acc("persist:pipe.tpl")}', '1')
|
||||
);
|
||||
}
|
||||
@ -259,8 +273,7 @@ class AccessorTest extends TestCase
|
||||
* @param $result
|
||||
*/
|
||||
public function testSmartAccessor($name, $accessor, $type, $code, $result) {
|
||||
$this->fenom->test = $this;
|
||||
$this->fenom->three = 3;
|
||||
$this->fenom->prop = "something";
|
||||
$this->fenom->addAccessorSmart($name, $accessor, $type);
|
||||
$this->assertRender($code, $result, $this->getVars());
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ namespace Fenom;
|
||||
class CustomProviderTest extends TestCase
|
||||
{
|
||||
|
||||
public function setUp()
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->fenom->addProvider("my", new Provider(FENOM_RESOURCES . '/provider'));
|
||||
|
@ -21,7 +21,7 @@ class FunctionsTest extends TestCase
|
||||
return $a + $i;
|
||||
}
|
||||
|
||||
public function setUp()
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->fenom->addFunctionSmart('sum', __CLASS__ . '::functionSum');
|
||||
|
@ -4,7 +4,7 @@ namespace Fenom;
|
||||
class MacrosTest extends TestCase
|
||||
{
|
||||
|
||||
public function setUp()
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->tpl("math.tpl",
|
||||
@ -115,12 +115,10 @@ class MacrosTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedExceptionMessage Undefined macro 'plus'
|
||||
* @expectedException \Fenom\Error\CompileException
|
||||
*/
|
||||
public function testImportMiss()
|
||||
{
|
||||
$this->expectException(exception: \Fenom\Error\CompileException::class);
|
||||
$this->expectExceptionMessage("Undefined macro 'plus'");
|
||||
$tpl = $this->fenom->compile('import_miss.tpl');
|
||||
|
||||
$this->assertSame(
|
||||
|
@ -11,7 +11,7 @@ class ProviderTest extends TestCase
|
||||
*/
|
||||
public $provider;
|
||||
|
||||
public function setUp()
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->tpl("template1.tpl", 'Template 1 {$a}');
|
||||
@ -30,6 +30,7 @@ class ProviderTest extends TestCase
|
||||
|
||||
public function testGetSource()
|
||||
{
|
||||
$time = 0.0;
|
||||
clearstatcache();
|
||||
$src = $this->provider->getSource("template1.tpl", $time);
|
||||
clearstatcache();
|
||||
@ -37,11 +38,9 @@ class ProviderTest extends TestCase
|
||||
$this->assertEquals(filemtime(FENOM_RESOURCES . '/template/template1.tpl'), $time);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
*/
|
||||
public function testGetSourceInvalid()
|
||||
{
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->provider->getSource("unexists.tpl", $time);
|
||||
}
|
||||
|
||||
@ -52,11 +51,9 @@ class ProviderTest extends TestCase
|
||||
$this->assertEquals(filemtime(FENOM_RESOURCES . '/template/template1.tpl'), $time);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
*/
|
||||
public function testGetLastModifiedInvalid()
|
||||
{
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->provider->getLastModified("unexists.tpl");
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ class RenderTest extends TestCase
|
||||
*/
|
||||
public static $render;
|
||||
|
||||
public static function setUpBeforeClass()
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
self::$render = new Render(Fenom::factory("."), function ($tpl) {
|
||||
echo "It is render's function " . $tpl["render"];
|
||||
@ -50,6 +50,8 @@ class RenderTest extends TestCase
|
||||
*/
|
||||
public function testFetchException()
|
||||
{
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessage("template error");
|
||||
$render = new Render(Fenom::factory("."), function () {
|
||||
echo "error";
|
||||
throw new \RuntimeException("template error");
|
||||
|
@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Fenom;
|
||||
|
||||
|
||||
class SandboxTest extends TestCase {
|
||||
|
||||
/**
|
||||
* @group sb
|
||||
*/
|
||||
public function test()
|
||||
{
|
||||
// return;
|
||||
// $this->fenom->setOptions(\Fenom::FORCE_VERIFY);
|
||||
// $this->fenom->addAccessorSmart('q', 'Navi::$q', \Fenom::ACCESSOR_VAR);
|
||||
// $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}');
|
||||
// var_dump($this->fenom->compileCode('{set $a=$one|min:0..$three|max:4}')->getBody());
|
||||
|
||||
// try {
|
||||
// var_dump($this->fenom->compileCode('{foreach $a as $k}A{$k:first}{foreachelse}B{/foreach}')->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;
|
||||
}
|
||||
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
<?php
|
||||
namespace Fenom;
|
||||
|
||||
class ScopeTest extends TestCase
|
||||
{
|
||||
public function openTag($tokenizer, $scope)
|
||||
{
|
||||
$this->assertInstanceOf('Fenom\Tokenizer', $tokenizer);
|
||||
$this->assertInstanceOf('Fenom\Scope', $scope);
|
||||
$scope["value"] = true;
|
||||
return "open-tag";
|
||||
}
|
||||
|
||||
public function closeTag($tokenizer, $scope)
|
||||
{
|
||||
$this->assertInstanceOf('Fenom\Tokenizer', $tokenizer);
|
||||
$this->assertInstanceOf('Fenom\Scope', $scope);
|
||||
$this->assertTrue($scope["value"]);
|
||||
return "close-tag";
|
||||
}
|
||||
|
||||
public function testBlock()
|
||||
{
|
||||
/*$scope = new Scope($this->fenom, new Template($this->fenom), 1, array(
|
||||
"open" => array($this, "openTag"),
|
||||
"close" => array($this, "closeTag")
|
||||
), 0);
|
||||
$tokenizer = new Tokenizer("1+1");
|
||||
$this->assertSame("open-tag /*#{$scope->id}#* /", $scope->open($tokenizer));
|
||||
$this->assertSame("close-tag", $scope->close($tokenizer));
|
||||
|
||||
$content = " some ?> content\n\nwith /*#9999999#* / many\n\tlines";
|
||||
$scope->tpl->_body = "start <?php ".$scope->open($tokenizer)." ?>".$content;
|
||||
$this->assertSame($content, $scope->getContent());*/
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Fenom;
|
||||
|
||||
|
||||
class TagOptionTest extends TestCase
|
||||
{
|
||||
|
||||
|
||||
public function testTrim()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@ use Fenom\Template,
|
||||
class TemplateTest extends TestCase
|
||||
{
|
||||
|
||||
public function setUp()
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->tpl('welcome.tpl', '<b>Welcome, {$username} ({$email})</b>');
|
||||
|
@ -80,6 +80,25 @@ class TokenizerTest extends TestCase
|
||||
$this->assertSame('}', $tokens->end()->current());
|
||||
}
|
||||
|
||||
public function testComplexTokens()
|
||||
{
|
||||
$text = "one\\two";
|
||||
$tokens = new Tokenizer($text);
|
||||
$this->assertSame("one", $tokens->current());
|
||||
$this->assertSame("\\", $tokens->next()->current());
|
||||
$this->assertSame("two", $tokens->next()->current());
|
||||
$this->assertFalse($tokens->next()->valid());
|
||||
|
||||
$text = "\\one\\two";
|
||||
|
||||
$tokens = new Tokenizer($text);
|
||||
$this->assertSame("\\", $tokens->current());
|
||||
$this->assertSame("one", $tokens->next()->current());
|
||||
$this->assertSame("\\", $tokens->next()->current());
|
||||
$this->assertSame("two", $tokens->next()->current());
|
||||
$this->assertFalse($tokens->next()->valid());
|
||||
}
|
||||
|
||||
public function testSkip()
|
||||
{
|
||||
$text = "1 foo: bar ( 3 + double ) ";
|
||||
|
Loading…
Reference in New Issue
Block a user