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
065ccaec23
commit
84dac62a85
@ -11,15 +11,17 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.0",
|
||||
"php": ">=8.0.0",
|
||||
"ext-tokenizer": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "<6.0",
|
||||
"satooshi/php-coveralls": "*"
|
||||
"phpunit/phpunit": "9.*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "Fenom\\": "src/" },
|
||||
"psr-4": { "Fenom\\": "src/Fenom" },
|
||||
"classmap": [ "src/Fenom.php" ]
|
||||
},
|
||||
"autoload-dev": {
|
||||
"classmap": [ "tests/cases" ]
|
||||
}
|
||||
}
|
||||
|
2792
composer.lock
generated
2792
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,6 @@
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
syntaxCheck="false"
|
||||
bootstrap="tests/autoload.php"
|
||||
>
|
||||
<php>
|
||||
@ -18,7 +17,7 @@
|
||||
</php>
|
||||
|
||||
<testsuites>
|
||||
<testsuite >
|
||||
<testsuite name="tests">
|
||||
<directory>./tests/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
@ -29,14 +28,6 @@
|
||||
</exclude>
|
||||
</groups>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory>./src/</directory>
|
||||
</whitelist>
|
||||
<blacklist>
|
||||
<directory>./tests/</directory>
|
||||
</blacklist>
|
||||
</filter>
|
||||
<logging>
|
||||
<log type="coverage-clover" target="build/logs/clover.xml"/>
|
||||
</logging>
|
||||
|
425
src/Fenom.php
425
src/Fenom.php
@ -8,7 +8,9 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
use Fenom\Error\CompileException;
|
||||
use Fenom\Provider;
|
||||
use Fenom\ProviderInterface;
|
||||
use Fenom\Render;
|
||||
use Fenom\Template;
|
||||
|
||||
/**
|
||||
@ -73,7 +75,7 @@ class Fenom
|
||||
* @var int[] of possible options, as associative array
|
||||
* @see setOptions
|
||||
*/
|
||||
private static $_options_list = array(
|
||||
private static $_options_list = [
|
||||
"disable_accessor" => self::DENY_ACCESSOR,
|
||||
"disable_methods" => self::DENY_METHODS,
|
||||
"disable_native_funcs" => self::DENY_NATIVE_FUNCS,
|
||||
@ -87,71 +89,71 @@ class Fenom
|
||||
"disable_php_calls" => self::DENY_PHP_CALLS,
|
||||
"disable_statics" => self::DENY_STATICS,
|
||||
"strip" => self::AUTO_STRIP,
|
||||
);
|
||||
];
|
||||
|
||||
/**
|
||||
* @var callable[]
|
||||
*/
|
||||
public $pre_filters = array();
|
||||
public array $pre_filters = [];
|
||||
|
||||
/**
|
||||
* @var callable[]
|
||||
*/
|
||||
public $filters = array();
|
||||
public array $filters = [];
|
||||
|
||||
/**
|
||||
* @var callable[]
|
||||
*/
|
||||
public $tag_filters = array();
|
||||
public array $tag_filters = [];
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
public $call_filters = array();
|
||||
public array $call_filters = [];
|
||||
|
||||
/**
|
||||
* @var callable[]
|
||||
*/
|
||||
public $post_filters = array();
|
||||
public array $post_filters = [];
|
||||
|
||||
/**
|
||||
* @var Fenom\Render[] Templates storage
|
||||
*/
|
||||
protected $_storage = array();
|
||||
protected array $_storage = [];
|
||||
|
||||
/**
|
||||
* @var string compile directory
|
||||
*/
|
||||
protected $_compile_dir = "/tmp";
|
||||
protected string $_compile_dir = "/tmp";
|
||||
|
||||
/**
|
||||
* @var string compile prefix ID template
|
||||
*/
|
||||
protected $_compile_id;
|
||||
protected string $_compile_id;
|
||||
|
||||
/**
|
||||
* @var string[] compile directory for custom provider
|
||||
*/
|
||||
protected $_compiles = array();
|
||||
protected array $_compiles = [];
|
||||
|
||||
/**
|
||||
* @var int masked options
|
||||
*/
|
||||
protected $_options = 0;
|
||||
protected int $_options = 0;
|
||||
|
||||
/**
|
||||
* @var ProviderInterface
|
||||
*/
|
||||
private $_provider;
|
||||
private ProviderInterface $_provider;
|
||||
/**
|
||||
* @var Fenom\ProviderInterface[]
|
||||
*/
|
||||
protected $_providers = array();
|
||||
protected array $_providers = [];
|
||||
|
||||
/**
|
||||
* @var string[] list of modifiers [modifier_name => callable]
|
||||
*/
|
||||
protected $_modifiers = array(
|
||||
protected array $_modifiers = [
|
||||
"upper" => 'strtoupper',
|
||||
"up" => 'strtoupper',
|
||||
"lower" => 'strtolower',
|
||||
@ -174,12 +176,12 @@ class Fenom
|
||||
"join" => 'Fenom\Modifier::join',
|
||||
"in" => 'Fenom\Modifier::in',
|
||||
"range" => 'Fenom\Modifier::range',
|
||||
);
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array of allowed PHP functions
|
||||
*/
|
||||
protected $_allowed_funcs = array(
|
||||
protected array $_allowed_funcs = [
|
||||
"count" => 1,
|
||||
"is_string" => 1,
|
||||
"is_array" => 1,
|
||||
@ -198,168 +200,168 @@ class Fenom
|
||||
"nl2br" => 1,
|
||||
"explode" => 1,
|
||||
"implode" => 1
|
||||
);
|
||||
];
|
||||
|
||||
/**
|
||||
* @var string[] the disabled functions by `disable_functions` PHP's option
|
||||
*/
|
||||
protected $_disabled_funcs;
|
||||
protected array $_disabled_funcs = [];
|
||||
|
||||
/**
|
||||
* @var array[] of compilers and functions
|
||||
*/
|
||||
protected $_actions = array(
|
||||
'foreach' => array( // {foreach ...} {break} {continue} {foreachelse} {/foreach}
|
||||
protected array $_actions = [
|
||||
'foreach' => [ // {foreach ...} {break} {continue} {foreachelse} {/foreach}
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::foreachOpen',
|
||||
'close' => 'Fenom\Compiler::foreachClose',
|
||||
'tags' => array(
|
||||
'tags' => [
|
||||
'foreachelse' => 'Fenom\Compiler::foreachElse',
|
||||
'break' => 'Fenom\Compiler::tagBreak',
|
||||
'continue' => 'Fenom\Compiler::tagContinue',
|
||||
),
|
||||
'float_tags' => array('break' => 1, 'continue' => 1)
|
||||
),
|
||||
'if' => array( // {if ...} {elseif ...} {else} {/if}
|
||||
],
|
||||
'float_tags' => ['break' => 1, 'continue' => 1]
|
||||
],
|
||||
'if' => [ // {if ...} {elseif ...} {else} {/if}
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::ifOpen',
|
||||
'close' => 'Fenom\Compiler::stdClose',
|
||||
'tags' => array(
|
||||
'tags' => [
|
||||
'elseif' => 'Fenom\Compiler::tagElseIf',
|
||||
'else' => 'Fenom\Compiler::tagElse'
|
||||
)
|
||||
),
|
||||
'switch' => array( // {switch ...} {case ..., ...} {default} {/switch}
|
||||
]
|
||||
],
|
||||
'switch' => [ // {switch ...} {case ..., ...} {default} {/switch}
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::switchOpen',
|
||||
'close' => 'Fenom\Compiler::switchClose',
|
||||
'tags' => array(
|
||||
'tags' => [
|
||||
'case' => 'Fenom\Compiler::tagCase',
|
||||
'default' => 'Fenom\Compiler::tagDefault'
|
||||
),
|
||||
'float_tags' => array('break' => 1)
|
||||
),
|
||||
'for' => array( // {for ...} {break} {continue} {/for}
|
||||
],
|
||||
'float_tags' => ['break' => 1]
|
||||
],
|
||||
'for' => [ // {for ...} {break} {continue} {/for}
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::forOpen',
|
||||
'close' => 'Fenom\Compiler::forClose',
|
||||
'tags' => array(
|
||||
'tags' => [
|
||||
'forelse' => 'Fenom\Compiler::forElse',
|
||||
'break' => 'Fenom\Compiler::tagBreak',
|
||||
'continue' => 'Fenom\Compiler::tagContinue',
|
||||
),
|
||||
'float_tags' => array('break' => 1, 'continue' => 1)
|
||||
),
|
||||
'while' => array( // {while ...} {break} {continue} {/while}
|
||||
],
|
||||
'float_tags' => ['break' => 1, 'continue' => 1]
|
||||
],
|
||||
'while' => [ // {while ...} {break} {continue} {/while}
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::whileOpen',
|
||||
'close' => 'Fenom\Compiler::stdClose',
|
||||
'tags' => array(
|
||||
'tags' => [
|
||||
'break' => 'Fenom\Compiler::tagBreak',
|
||||
'continue' => 'Fenom\Compiler::tagContinue',
|
||||
),
|
||||
'float_tags' => array('break' => 1, 'continue' => 1)
|
||||
),
|
||||
'include' => array( // {include ...}
|
||||
],
|
||||
'float_tags' => ['break' => 1, 'continue' => 1]
|
||||
],
|
||||
'include' => [ // {include ...}
|
||||
'type' => self::INLINE_COMPILER,
|
||||
'parser' => 'Fenom\Compiler::tagInclude'
|
||||
),
|
||||
'insert' => array( // {include ...}
|
||||
],
|
||||
'insert' => [ // {include ...}
|
||||
'type' => self::INLINE_COMPILER,
|
||||
'parser' => 'Fenom\Compiler::tagInsert'
|
||||
),
|
||||
'var' => array( // {var ...}
|
||||
],
|
||||
'var' => [ // {var ...}
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::setOpen',
|
||||
'close' => 'Fenom\Compiler::setClose'
|
||||
),
|
||||
'set' => array( // {set ...}
|
||||
],
|
||||
'set' => [ // {set ...}
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::setOpen',
|
||||
'close' => 'Fenom\Compiler::setClose'
|
||||
),
|
||||
'add' => array( // {add ...}
|
||||
],
|
||||
'add' => [ // {add ...}
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::setOpen',
|
||||
'close' => 'Fenom\Compiler::setClose'
|
||||
),
|
||||
'do' => array( // {do ...}
|
||||
],
|
||||
'do' => [ // {do ...}
|
||||
'type' => self::INLINE_COMPILER,
|
||||
'parser' => 'Fenom\Compiler::tagDo'
|
||||
),
|
||||
'block' => array( // {block ...} {parent} {/block}
|
||||
],
|
||||
'block' => [ // {block ...} {parent} {/block}
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::tagBlockOpen',
|
||||
'close' => 'Fenom\Compiler::tagBlockClose',
|
||||
'tags' => array('parent' => 'Fenom\Compiler::tagParent'),
|
||||
'float_tags' => array('parent' => 1)
|
||||
),
|
||||
'extends' => array( // {extends ...}
|
||||
'tags' => ['parent' => 'Fenom\Compiler::tagParent'],
|
||||
'float_tags' => ['parent' => 1]
|
||||
],
|
||||
'extends' => [ // {extends ...}
|
||||
'type' => self::INLINE_COMPILER,
|
||||
'parser' => 'Fenom\Compiler::tagExtends'
|
||||
),
|
||||
'use' => array( // {use}
|
||||
],
|
||||
'use' => [ // {use}
|
||||
'type' => self::INLINE_COMPILER,
|
||||
'parser' => 'Fenom\Compiler::tagUse'
|
||||
),
|
||||
'filter' => array( // {filter} ... {/filter}
|
||||
],
|
||||
'filter' => [ // {filter} ... {/filter}
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::filterOpen',
|
||||
'close' => 'Fenom\Compiler::filterClose'
|
||||
),
|
||||
'macro' => array(
|
||||
],
|
||||
'macro' => [
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::macroOpen',
|
||||
'close' => 'Fenom\Compiler::macroClose'
|
||||
),
|
||||
'import' => array(
|
||||
],
|
||||
'import' => [
|
||||
'type' => self::INLINE_COMPILER,
|
||||
'parser' => 'Fenom\Compiler::tagImport'
|
||||
),
|
||||
'cycle' => array(
|
||||
],
|
||||
'cycle' => [
|
||||
'type' => self::INLINE_COMPILER,
|
||||
'parser' => 'Fenom\Compiler::tagCycle'
|
||||
),
|
||||
'raw' => array(
|
||||
],
|
||||
'raw' => [
|
||||
'type' => self::INLINE_COMPILER,
|
||||
'parser' => 'Fenom\Compiler::tagRaw'
|
||||
),
|
||||
'autoescape' => array( // deprecated
|
||||
],
|
||||
'autoescape' => [ // deprecated
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::escapeOpen',
|
||||
'close' => 'Fenom\Compiler::nope'
|
||||
),
|
||||
'escape' => array(
|
||||
],
|
||||
'escape' => [
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::escapeOpen',
|
||||
'close' => 'Fenom\Compiler::nope'
|
||||
),
|
||||
'strip' => array(
|
||||
],
|
||||
'strip' => [
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::stripOpen',
|
||||
'close' => 'Fenom\Compiler::nope'
|
||||
),
|
||||
'ignore' => array(
|
||||
],
|
||||
'ignore' => [
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::ignoreOpen',
|
||||
'close' => 'Fenom\Compiler::nope'
|
||||
),
|
||||
'unset' => array(
|
||||
],
|
||||
'unset' => [
|
||||
'type' => self::INLINE_COMPILER,
|
||||
'parser' => 'Fenom\Compiler::tagUnset'
|
||||
),
|
||||
'paste' => array( // {include ...}
|
||||
],
|
||||
'paste' => [ // {include ...}
|
||||
'type' => self::INLINE_COMPILER,
|
||||
'parser' => 'Fenom\Compiler::tagPaste'
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* List of tests
|
||||
* @see https://github.com/bzick/fenom/blob/develop/docs/operators.md#test-operator
|
||||
* @var array
|
||||
*/
|
||||
protected $_tests = array(
|
||||
protected array $_tests = [
|
||||
'integer' => 'is_int(%s)',
|
||||
'int' => 'is_int(%s)',
|
||||
'float' => 'is_float(%s)',
|
||||
@ -385,9 +387,9 @@ class Fenom
|
||||
'odd' => '(%s & 1)',
|
||||
'even' => '!(%s %% 2)',
|
||||
'third' => '!(%s %% 3)'
|
||||
);
|
||||
];
|
||||
|
||||
protected $_accessors = array(
|
||||
protected array $_accessors = [
|
||||
'get' => 'Fenom\Accessor::getVar',
|
||||
'env' => 'Fenom\Accessor::getVar',
|
||||
'post' => 'Fenom\Accessor::getVar',
|
||||
@ -405,7 +407,7 @@ class Fenom
|
||||
'tag' => 'Fenom\Accessor::Tag',
|
||||
'fetch' => 'Fenom\Accessor::fetch',
|
||||
'block' => 'Fenom\Accessor::block',
|
||||
);
|
||||
];
|
||||
|
||||
/**
|
||||
* Just factory
|
||||
@ -416,7 +418,11 @@ class Fenom
|
||||
* @throws InvalidArgumentException
|
||||
* @return Fenom
|
||||
*/
|
||||
public static function factory($source, $compile_dir = '/tmp', $options = 0)
|
||||
public static function factory(
|
||||
string|Fenom\ProviderInterface $source,
|
||||
string $compile_dir = '/tmp',
|
||||
int|array $options = 0
|
||||
): Fenom
|
||||
{
|
||||
if (is_string($source)) {
|
||||
$provider = new Fenom\Provider($source);
|
||||
@ -426,7 +432,6 @@ class Fenom
|
||||
throw new InvalidArgumentException("Source must be a valid path or provider object");
|
||||
}
|
||||
$fenom = new static($provider);
|
||||
/* @var Fenom $fenom */
|
||||
$fenom->setCompileDir($compile_dir);
|
||||
if ($options) {
|
||||
$fenom->setOptions($options);
|
||||
@ -447,9 +452,9 @@ class Fenom
|
||||
*
|
||||
* @param string $dir directory to store compiled templates in
|
||||
* @throws LogicException
|
||||
* @return Fenom
|
||||
* @return $this
|
||||
*/
|
||||
public function setCompileDir($dir)
|
||||
public function setCompileDir(string $dir): static
|
||||
{
|
||||
if (!is_writable($dir)) {
|
||||
throw new LogicException("Cache directory $dir is not writable");
|
||||
@ -462,9 +467,9 @@ class Fenom
|
||||
* Set compile prefix ID template
|
||||
*
|
||||
* @param string $id prefix ID to store compiled templates
|
||||
* @return Fenom
|
||||
* @return $this
|
||||
*/
|
||||
public function setCompileId($id)
|
||||
public function setCompileId(string $id): static
|
||||
{
|
||||
$this->_compile_id = $id;
|
||||
return $this;
|
||||
@ -473,15 +478,18 @@ class Fenom
|
||||
/**
|
||||
*
|
||||
* @param callable $cb
|
||||
* @return self
|
||||
* @return $this
|
||||
*/
|
||||
public function addPreFilter($cb)
|
||||
public function addPreFilter(callable $cb): static
|
||||
{
|
||||
$this->pre_filters[] = $cb;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPreFilters()
|
||||
/**
|
||||
* @return callable[]
|
||||
*/
|
||||
public function getPreFilters(): array
|
||||
{
|
||||
return $this->pre_filters;
|
||||
}
|
||||
@ -489,16 +497,18 @@ class Fenom
|
||||
/**
|
||||
*
|
||||
* @param callable $cb
|
||||
* @return self
|
||||
* @return $this
|
||||
*/
|
||||
public function addPostFilter($cb)
|
||||
public function addPostFilter(callable $cb): static
|
||||
{
|
||||
$this->post_filters[] = $cb;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function getPostFilters()
|
||||
/**
|
||||
* @return callable[]
|
||||
*/
|
||||
public function getPostFilters(): array
|
||||
{
|
||||
return $this->post_filters;
|
||||
}
|
||||
@ -507,14 +517,14 @@ class Fenom
|
||||
* @param callable $cb
|
||||
* @return self
|
||||
*/
|
||||
public function addFilter($cb)
|
||||
public function addFilter(callable $cb): static
|
||||
{
|
||||
$this->filters[] = $cb;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function getFilters()
|
||||
public function getFilters(): array
|
||||
{
|
||||
return $this->filters;
|
||||
}
|
||||
@ -523,14 +533,14 @@ class Fenom
|
||||
* @param callable $cb
|
||||
* @return self
|
||||
*/
|
||||
public function addTagFilter($cb)
|
||||
public function addTagFilter(callable $cb): static
|
||||
{
|
||||
$this->tag_filters[] = $cb;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function getTagFilters()
|
||||
public function getTagFilters(): array
|
||||
{
|
||||
return $this->tag_filters;
|
||||
}
|
||||
@ -542,7 +552,7 @@ class Fenom
|
||||
* @param callable $callback the modifier callback
|
||||
* @return Fenom
|
||||
*/
|
||||
public function addModifier($modifier, $callback)
|
||||
public function addModifier(string $modifier, callable $callback): static
|
||||
{
|
||||
$this->_modifiers[$modifier] = $callback;
|
||||
return $this;
|
||||
@ -555,7 +565,7 @@ class Fenom
|
||||
* @param callable $parser
|
||||
* @return Fenom
|
||||
*/
|
||||
public function addCompiler($compiler, $parser)
|
||||
public function addCompiler(string $compiler, callable $parser): static
|
||||
{
|
||||
$this->_actions[$compiler] = array(
|
||||
'type' => self::INLINE_COMPILER,
|
||||
@ -569,7 +579,7 @@ class Fenom
|
||||
* @param string|object $storage
|
||||
* @return $this
|
||||
*/
|
||||
public function addCompilerSmart($compiler, $storage)
|
||||
public function addCompilerSmart(string $compiler, string|object $storage): static
|
||||
{
|
||||
if (method_exists($storage, "tag" . $compiler)) {
|
||||
$this->_actions[$compiler] = array(
|
||||
@ -585,11 +595,17 @@ class Fenom
|
||||
*
|
||||
* @param string $compiler
|
||||
* @param callable $open_parser
|
||||
* @param callable|string $close_parser
|
||||
* @param callable $close_parser
|
||||
* @param array $tags
|
||||
* @return Fenom
|
||||
*/
|
||||
public function addBlockCompiler($compiler, $open_parser, $close_parser = self::DEFAULT_CLOSE_COMPILER, array $tags = array()) {
|
||||
public function addBlockCompiler(
|
||||
string $compiler,
|
||||
callable $open_parser,
|
||||
callable $close_parser = self::DEFAULT_CLOSE_COMPILER,
|
||||
array $tags = []
|
||||
): static
|
||||
{
|
||||
$this->_actions[$compiler] = array(
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => $open_parser,
|
||||
@ -600,14 +616,19 @@ class Fenom
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $compiler
|
||||
* @param $storage
|
||||
* @param string $compiler
|
||||
* @param string|object $storage
|
||||
* @param array $tags
|
||||
* @param array $floats
|
||||
* @throws LogicException
|
||||
* @return Fenom
|
||||
*/
|
||||
public function addBlockCompilerSmart($compiler, $storage, array $tags, array $floats = array())
|
||||
public function addBlockCompilerSmart(
|
||||
string $compiler,
|
||||
string|object $storage,
|
||||
array $tags,
|
||||
array $floats = []
|
||||
): static
|
||||
{
|
||||
$c = array(
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
@ -641,10 +662,10 @@ class Fenom
|
||||
/**
|
||||
* @param string $function
|
||||
* @param callable $callback
|
||||
* @param callable|string $parser
|
||||
* @param callable $parser
|
||||
* @return Fenom
|
||||
*/
|
||||
public function addFunction($function, $callback, $parser = self::DEFAULT_FUNC_PARSER)
|
||||
public function addFunction(string $function, callable $callback, callable $parser = self::DEFAULT_FUNC_PARSER): static
|
||||
{
|
||||
$this->_actions[$function] = array(
|
||||
'type' => self::INLINE_FUNCTION,
|
||||
@ -659,7 +680,7 @@ class Fenom
|
||||
* @param callable $callback
|
||||
* @return Fenom
|
||||
*/
|
||||
public function addFunctionSmart($function, $callback)
|
||||
public function addFunctionSmart(string $function, callable $callback): static
|
||||
{
|
||||
$this->_actions[$function] = array(
|
||||
'type' => self::INLINE_FUNCTION,
|
||||
@ -672,11 +693,16 @@ class Fenom
|
||||
/**
|
||||
* @param string $function
|
||||
* @param callable $callback
|
||||
* @param callable|string $parser_open
|
||||
* @param callable|string $parser_close
|
||||
* @param callable $parser_open
|
||||
* @param callable $parser_close
|
||||
* @return Fenom
|
||||
*/
|
||||
public function addBlockFunction($function, $callback, $parser_open = self::DEFAULT_FUNC_OPEN, $parser_close = self::DEFAULT_FUNC_CLOSE)
|
||||
public function addBlockFunction(
|
||||
string $function,
|
||||
callable $callback,
|
||||
callable $parser_open = self::DEFAULT_FUNC_OPEN,
|
||||
callable $parser_close = self::DEFAULT_FUNC_CLOSE
|
||||
): static
|
||||
{
|
||||
$this->_actions[$function] = array(
|
||||
'type' => self::BLOCK_FUNCTION,
|
||||
@ -691,7 +717,7 @@ class Fenom
|
||||
* @param array $funcs
|
||||
* @return Fenom
|
||||
*/
|
||||
public function addAllowedFunctions(array $funcs)
|
||||
public function addAllowedFunctions(array $funcs): static
|
||||
{
|
||||
$this->_allowed_funcs = $this->_allowed_funcs + array_flip($funcs);
|
||||
return $this;
|
||||
@ -700,31 +726,32 @@ class Fenom
|
||||
/**
|
||||
* Add custom test
|
||||
* @param string $name test name
|
||||
* @param string $code test PHP code. Code may contains placeholder %s, which will be replaced by test-value. For example: is_callable(%s)
|
||||
* @param string $code test PHP code. Code may contain placeholder %s, which will be replaced by test-value. For example: is_callable(%s)
|
||||
*/
|
||||
public function addTest($name, $code)
|
||||
public function addTest(string $name, string $code): static
|
||||
{
|
||||
$this->_tests[$name] = $code;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get test code by name
|
||||
* @param string $name
|
||||
* @return string|bool
|
||||
* @return string
|
||||
*/
|
||||
public function getTest($name)
|
||||
public function getTest(string $name): string
|
||||
{
|
||||
return isset($this->_tests[$name]) ? $this->_tests[$name] : false;
|
||||
return $this->_tests[$name] ?? "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return modifier function
|
||||
*
|
||||
* @param string $modifier
|
||||
* @param Fenom\Template $template
|
||||
* @param Template|null $template
|
||||
* @return mixed
|
||||
*/
|
||||
public function getModifier($modifier, Template $template = null)
|
||||
public function getModifier(string $modifier, Fenom\Template $template = null): static
|
||||
{
|
||||
if (isset($this->_modifiers[$modifier])) {
|
||||
return $this->_modifiers[$modifier];
|
||||
@ -741,7 +768,7 @@ class Fenom
|
||||
* @param Fenom\Template $template
|
||||
* @return bool
|
||||
*/
|
||||
protected function _loadModifier($modifier, $template)
|
||||
protected function _loadModifier(string $modifier, Fenom\Template $template): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -750,10 +777,10 @@ class Fenom
|
||||
* Returns tag info
|
||||
*
|
||||
* @param string $tag
|
||||
* @param Fenom\Template $template
|
||||
* @return string|bool
|
||||
* @param Template|null $template
|
||||
* @return array|null
|
||||
*/
|
||||
public function getTag($tag, Template $template = null)
|
||||
public function getTag(string $tag, Template $template = null): ?array
|
||||
{
|
||||
if (isset($this->_actions[$tag])) {
|
||||
return $this->_actions[$tag];
|
||||
@ -766,11 +793,11 @@ class Fenom
|
||||
* Tags autoloader
|
||||
* @param string $tag
|
||||
* @param Fenom\Template $template
|
||||
* @return bool
|
||||
* @return array|null
|
||||
*/
|
||||
protected function _loadTag($tag, $template)
|
||||
protected function _loadTag(string $tag, Template $template): ?array
|
||||
{
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -779,13 +806,12 @@ class Fenom
|
||||
* @param string $function the function name
|
||||
* @return bool
|
||||
*/
|
||||
public function isAllowedFunction($function)
|
||||
public function isAllowedFunction(string $function): bool
|
||||
{
|
||||
$function = (string) $function;
|
||||
$allow = ($this->_options & self::DENY_NATIVE_FUNCS)
|
||||
? isset($this->_allowed_funcs[$function])
|
||||
: function_exists($function);
|
||||
return $allow && !in_array($function, $this->getDisabledFuncs(), true);
|
||||
return $allow && !in_array($function, $this->_getDisabledFuncs(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -793,18 +819,8 @@ class Fenom
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function _getDisabledFuncs()
|
||||
protected function _getDisabledFuncs(): array
|
||||
{
|
||||
if (!is_array($this->_disabled_funcs)) {
|
||||
$disabled = ini_get('disable_functions');
|
||||
// adds execution functions to disabled for security
|
||||
$this->_disabled_funcs = array_merge(
|
||||
empty($disabled) ? [] : explode(',', $disabled),
|
||||
array('exec', 'system', 'passthru', 'shell_exec', 'pcntl_exec', 'proc_open', 'popen'),
|
||||
array('call_user_func', 'call_user_func_array')
|
||||
);
|
||||
}
|
||||
|
||||
return $this->_disabled_funcs;
|
||||
}
|
||||
|
||||
@ -812,9 +828,9 @@ class Fenom
|
||||
* @param string $tag
|
||||
* @return array
|
||||
*/
|
||||
public function getTagOwners($tag)
|
||||
public function getTagOwners(string $tag): array
|
||||
{
|
||||
$tags = array();
|
||||
$tags = [];
|
||||
foreach ($this->_actions as $owner => $params) {
|
||||
if (isset($params["tags"][$tag])) {
|
||||
$tags[] = $owner;
|
||||
@ -828,10 +844,10 @@ class Fenom
|
||||
*
|
||||
* @param string $scm scheme name
|
||||
* @param Fenom\ProviderInterface $provider provider object
|
||||
* @param string $compile_path
|
||||
* @param string|null $compile_path
|
||||
* @return $this
|
||||
*/
|
||||
public function addProvider($scm, \Fenom\ProviderInterface $provider, $compile_path = null)
|
||||
public function addProvider(string $scm, ProviderInterface $provider, string $compile_path = null): static
|
||||
{
|
||||
$this->_providers[$scm] = $provider;
|
||||
if ($compile_path) {
|
||||
@ -845,7 +861,7 @@ class Fenom
|
||||
* @param int|array $options
|
||||
* @return $this
|
||||
*/
|
||||
public function setOptions($options)
|
||||
public function setOptions(int|array $options): static
|
||||
{
|
||||
if (is_array($options)) {
|
||||
$options = self::_makeMask($options, self::$_options_list, $this->_options);
|
||||
@ -859,7 +875,7 @@ class Fenom
|
||||
* Get options as bits
|
||||
* @return int
|
||||
*/
|
||||
public function getOptions()
|
||||
public function getOptions(): int
|
||||
{
|
||||
return $this->_options;
|
||||
}
|
||||
@ -870,7 +886,7 @@ class Fenom
|
||||
* @param callable $parser
|
||||
* @return Fenom
|
||||
*/
|
||||
public function addAccessor($name, $parser)
|
||||
public function addAccessor(string $name, callable $parser): static
|
||||
{
|
||||
$this->_accessors[$name] = $parser;
|
||||
return $this;
|
||||
@ -883,7 +899,7 @@ class Fenom
|
||||
* @param string $parser
|
||||
* @return Fenom
|
||||
*/
|
||||
public function addAccessorSmart($name, $accessor, $parser = self::ACCESSOR_VAR)
|
||||
public function addAccessorSmart(string $name, mixed $accessor, string $parser = self::ACCESSOR_VAR): static
|
||||
{
|
||||
$this->_accessors[$name] = array(
|
||||
"accessor" => $accessor,
|
||||
@ -898,7 +914,7 @@ class Fenom
|
||||
* @param callable $callback
|
||||
* @return Fenom
|
||||
*/
|
||||
public function addAccessorCallback($name, $callback)
|
||||
public function addAccessorCallback(string $name, callable $callback): static
|
||||
{
|
||||
$this->_accessors[$name] = array(
|
||||
"callback" => $callback
|
||||
@ -911,7 +927,7 @@ class Fenom
|
||||
* @param string $name
|
||||
* @return Fenom
|
||||
*/
|
||||
public function removeAccessor($name)
|
||||
public function removeAccessor(string $name): static
|
||||
{
|
||||
unset($this->_accessors[$name]);
|
||||
return $this;
|
||||
@ -920,10 +936,10 @@ class Fenom
|
||||
/**
|
||||
* Get an accessor
|
||||
* @param string $name
|
||||
* @param string $key
|
||||
* @return callable
|
||||
* @param string|null $key
|
||||
* @return callable|null
|
||||
*/
|
||||
public function getAccessor($name, $key = null)
|
||||
public function getAccessor(string $name,string $key = null): ?callable
|
||||
{
|
||||
if(isset($this->_accessors[$name])) {
|
||||
if($key) {
|
||||
@ -932,7 +948,7 @@ class Fenom
|
||||
return $this->_accessors[$name];
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -942,18 +958,18 @@ class Fenom
|
||||
* @param string $pattern
|
||||
* @return $this
|
||||
*/
|
||||
public function addCallFilter($pattern)
|
||||
public function addCallFilter(string $pattern): static
|
||||
{
|
||||
$this->call_filters[] = $pattern;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool|string $scm
|
||||
* @return Fenom\ProviderInterface
|
||||
* @param string|null $scm
|
||||
* @return ProviderInterface
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function getProvider($scm = false)
|
||||
public function getProvider(string $scm = null): Fenom\ProviderInterface
|
||||
{
|
||||
if ($scm) {
|
||||
if (isset($this->_providers[$scm])) {
|
||||
@ -971,7 +987,7 @@ class Fenom
|
||||
*
|
||||
* @return Fenom\Template
|
||||
*/
|
||||
public function getRawTemplate(Template $parent = null)
|
||||
public function getRawTemplate(Template $parent = null): Template
|
||||
{
|
||||
return new Template($this, $this->_options, $parent);
|
||||
}
|
||||
@ -983,20 +999,22 @@ class Fenom
|
||||
* 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
|
||||
* @throws CompileException
|
||||
*/
|
||||
public function display($template, array $vars = array())
|
||||
public function display(string|array $template, array $vars = array()): Fenom\Render
|
||||
{
|
||||
return $this->getTemplate($template)->display($vars);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string|array $template name of template.
|
||||
* @param array|string $template name of template.
|
||||
* If it is array of names of templates they will be extended from left to right.
|
||||
* @param array $vars array of data for template
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function fetch($template, array $vars = array())
|
||||
public function fetch(array|string $template, array $vars = array()): mixed
|
||||
{
|
||||
return $this->getTemplate($template)->fetch($vars);
|
||||
}
|
||||
@ -1004,14 +1022,15 @@ class Fenom
|
||||
/**
|
||||
* Creates pipe-line of template's data to callback
|
||||
* @note Method not works correctly in old PHP 5.3.*
|
||||
* @param string|array $template name of the template.
|
||||
* @param array|string $template name of the template.
|
||||
* If it is array of names of templates they will be extended from left to right.
|
||||
* @param callable $callback template's data handler
|
||||
* @param array $vars
|
||||
* @param float $chunk amount of bytes of chunk
|
||||
* @param int $chunk amount of bytes of chunk
|
||||
* @return array
|
||||
* @throws CompileException
|
||||
*/
|
||||
public function pipe($template, $callback, array $vars = array(), $chunk = 1e6)
|
||||
public function pipe(array|string $template, callable $callback, array $vars = array(), int $chunk = 1_000_000): array
|
||||
{
|
||||
ob_start($callback, $chunk, PHP_OUTPUT_HANDLER_STDFLAGS);
|
||||
$data = $this->getTemplate($template)->display($vars);
|
||||
@ -1022,11 +1041,12 @@ class Fenom
|
||||
/**
|
||||
* Get template by name
|
||||
*
|
||||
* @param string $template template name with schema
|
||||
* @param string|array $template template name with schema
|
||||
* @param int $options additional options and flags
|
||||
* @return Fenom\Template
|
||||
* @return Fenom\Render
|
||||
* @throws CompileException
|
||||
*/
|
||||
public function getTemplate($template, $options = 0)
|
||||
public function getTemplate(string|array $template, int $options = 0): Render
|
||||
{
|
||||
$options |= $this->_options;
|
||||
if (is_array($template)) {
|
||||
@ -1054,7 +1074,7 @@ class Fenom
|
||||
* @param string $template
|
||||
* @return bool
|
||||
*/
|
||||
public function templateExists($template)
|
||||
public function templateExists(string $template): bool
|
||||
{
|
||||
$key = $this->_options . "@" . $template;
|
||||
if (isset($this->_storage[$key])) { // already loaded
|
||||
@ -1076,8 +1096,9 @@ class Fenom
|
||||
* @param string $template
|
||||
* @param int $opts
|
||||
* @return Fenom\Render
|
||||
* @throws CompileException
|
||||
*/
|
||||
protected function _load($template, $opts)
|
||||
protected function _load(string $template, int $opts): Render
|
||||
{
|
||||
$file_name = $this->getCompileName($template, $opts);
|
||||
if (is_file($this->_compile_dir . "/" . $file_name)) {
|
||||
@ -1101,7 +1122,7 @@ class Fenom
|
||||
* @param int $options additional options
|
||||
* @return string
|
||||
*/
|
||||
public function getCompileName($tpl, $options = 0)
|
||||
public function getCompileName(array|string $tpl, int $options = 0): string
|
||||
{
|
||||
$options = $this->_options | $options;
|
||||
if (is_array($tpl)) {
|
||||
@ -1123,13 +1144,13 @@ class Fenom
|
||||
/**
|
||||
* Compile and save template
|
||||
*
|
||||
* @param string|array $tpl
|
||||
* @param array|string $tpl
|
||||
* @param bool $store store template on disk
|
||||
* @param int $options
|
||||
* @return Template
|
||||
* @throws CompileException
|
||||
* @return \Fenom\Template
|
||||
*/
|
||||
public function compile($tpl, $store = true, $options = 0)
|
||||
public function compile(array|string $tpl, bool $store = true, int $options = 0): Template
|
||||
{
|
||||
if (is_string($tpl)) {
|
||||
$template = $this->getRawTemplate()->load($tpl);
|
||||
@ -1157,17 +1178,17 @@ class Fenom
|
||||
/**
|
||||
* Flush internal template in-memory-cache
|
||||
*/
|
||||
public function flush()
|
||||
public function flush(): void
|
||||
{
|
||||
$this->_storage = array();
|
||||
$this->_storage = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all compiled templates
|
||||
*/
|
||||
public function clearAllCompiles()
|
||||
public function clearAllCompiles(): void
|
||||
{
|
||||
\Fenom\Provider::clean($this->_compile_dir);
|
||||
Provider::clean($this->_compile_dir);
|
||||
$this->flush();
|
||||
}
|
||||
|
||||
@ -1178,7 +1199,7 @@ class Fenom
|
||||
* @param string $name
|
||||
* @return Fenom\Template
|
||||
*/
|
||||
public function compileCode($code, $name = 'Runtime compile')
|
||||
public function compileCode(string $code, string $name = 'Runtime compile'): Template
|
||||
{
|
||||
return $this->getRawTemplate()->source($name, $code);
|
||||
}
|
||||
@ -1191,9 +1212,9 @@ class Fenom
|
||||
* @param array $options possible values, ["a" => 0b001, "b" => 0b010, "c" => 0b100]
|
||||
* @param int $mask the initial value of the mask
|
||||
* @return int result, ( $mask | a ) & ~b
|
||||
* @throws \RuntimeException if key from custom assoc doesn't exists into possible values
|
||||
* @throws \RuntimeException if key from custom assoc doesn't exist into possible values
|
||||
*/
|
||||
private static function _makeMask(array $values, array $options, $mask = 0)
|
||||
private static function _makeMask(array $values, array $options, int $mask = 0): int
|
||||
{
|
||||
foreach ($values as $key => $value) {
|
||||
if (isset($options[$key])) {
|
||||
@ -1208,24 +1229,4 @@ class Fenom
|
||||
}
|
||||
return $mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register PSR-0 autoload
|
||||
* @param string $dir custom directory for autoloading, if NULL — autoload itself
|
||||
* @return bool
|
||||
*/
|
||||
public static function registerAutoload($dir = null)
|
||||
{
|
||||
if (!$dir) {
|
||||
$dir = __DIR__;
|
||||
}
|
||||
return spl_autoload_register(
|
||||
function ($classname) use ($dir) {
|
||||
$file = $dir . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $classname) . '.php';
|
||||
if (is_file($file)) {
|
||||
require_once $file;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ class Accessor {
|
||||
*/
|
||||
public static function getVar(Tokenizer $tokens, Template $tpl)
|
||||
{
|
||||
$name = $tokens->prev[Tokenizer::TEXT];
|
||||
$name = $tokens->prevToken()[Tokenizer::TEXT];
|
||||
if(isset(self::$vars[$name])) {
|
||||
$var = $tpl->parseVariable($tokens, self::$vars[$name]);
|
||||
return "(isset($var) ? $var : null)";
|
||||
|
@ -24,7 +24,7 @@ class UnexpectedTokenException extends \RuntimeException
|
||||
} else {
|
||||
$expect = "";
|
||||
}
|
||||
if (!$tokens->curr) {
|
||||
if (!$tokens->currToken()) {
|
||||
$this->message = "Unexpected end of " . ($where ? : "expression") . "$expect";
|
||||
} else {
|
||||
$this->message = "Unexpected token '" . $tokens->current() . "' in " . ($where ? : "expression") . "$expect";
|
||||
|
@ -951,8 +951,8 @@ class Template extends Render
|
||||
$code .= '->' . $tokens->next()->getAndNext();
|
||||
}
|
||||
if ($tokens->current() === "." || $tokens->current() === "[") {
|
||||
$code = substr($code, 0, -strlen($tokens->prev[1]));
|
||||
$code .= $this->parseVariable($tokens, $tokens->prev[1]);
|
||||
$code = substr($code, 0, -strlen($tokens->prevToken()[1]));
|
||||
$code .= $this->parseVariable($tokens, $tokens->prevToken()[1]);
|
||||
}
|
||||
} while ($tokens->is('(', T_OBJECT_OPERATOR));
|
||||
|
||||
|
@ -19,9 +19,6 @@ use Fenom\Error\UnexpectedTokenException;
|
||||
* - Line number of the token
|
||||
*
|
||||
* @see http://php.net/tokenizer
|
||||
* @property array $prev the previous token
|
||||
* @property array $curr the current token
|
||||
* @property array $next the next token
|
||||
*
|
||||
* @package Fenom
|
||||
* @author Ivan Shalganov <a.cobest@gmail.com>
|
||||
@ -70,18 +67,18 @@ class Tokenizer
|
||||
*/
|
||||
const MACRO_COND = 1008;
|
||||
|
||||
public $tokens;
|
||||
public $p = 0;
|
||||
public $quotes = 0;
|
||||
private $_max = 0;
|
||||
private $_last_no = 0;
|
||||
public array $tokens;
|
||||
public int $p = 0;
|
||||
public int $quotes = 0;
|
||||
private int $_max;
|
||||
private mixed $_last_no;
|
||||
|
||||
/**
|
||||
* @see http://docs.php.net/manual/en/tokens.php
|
||||
* @var array groups of tokens
|
||||
*/
|
||||
public static $macros = array(
|
||||
self::MACRO_STRING => array(
|
||||
public static array $macros = [
|
||||
self::MACRO_STRING => [
|
||||
\T_ABSTRACT => 1, \T_ARRAY => 1, \T_AS => 1, \T_BREAK => 1,
|
||||
\T_CASE => 1, \T_CATCH => 1, \T_CLASS => 1,
|
||||
\T_CLASS_C => 1, \T_CLONE => 1, \T_CONST => 1, \T_CONTINUE => 1,
|
||||
@ -92,23 +89,23 @@ class Tokenizer
|
||||
\T_EXTENDS => 1, \T_FILE => 1, \T_FINAL => 1, \T_FOR => 1,
|
||||
\T_FOREACH => 1, \T_FUNCTION => 1, \T_FUNC_C => 1, \T_GLOBAL => 1,
|
||||
\T_GOTO => 1, \T_HALT_COMPILER => 1, \T_IF => 1, \T_IMPLEMENTS => 1,
|
||||
\T_INCLUDE => 1, \T_INCLUDE_ONCE => 1, \T_INSTANCEOF => 1, 341 /* T_INSTEADOF */ => 1,
|
||||
\T_INCLUDE => 1, \T_INCLUDE_ONCE => 1, \T_INSTANCEOF => 1, \T_INSTEADOF => 1,
|
||||
\T_INTERFACE => 1, \T_ISSET => 1, \T_LINE => 1, \T_LIST => 1,
|
||||
\T_LOGICAL_AND => 1, \T_LOGICAL_OR => 1, \T_LOGICAL_XOR => 1, \T_METHOD_C => 1,
|
||||
\T_NAMESPACE => 1, \T_NS_C => 1, \T_NEW => 1, \T_PRINT => 1,
|
||||
\T_PRIVATE => 1, \T_PUBLIC => 1, \T_PROTECTED => 1, \T_REQUIRE => 1,
|
||||
\T_REQUIRE_ONCE => 1, \T_RETURN => 1, \T_RETURN => 1, \T_STRING => 1,
|
||||
\T_SWITCH => 1, \T_THROW => 1, 355 /* T_TRAIT */ => 1, 365 /* T_TRAIT_C */ => 1,
|
||||
\T_REQUIRE_ONCE => 1, \T_RETURN => 1, \T_STRING => 1,
|
||||
\T_SWITCH => 1, \T_THROW => 1, \T_TRAIT => 1, \T_TRAIT_C => 1,
|
||||
\T_TRY => 1, \T_UNSET => 1, \T_USE => 1, \T_VAR => 1,
|
||||
\T_WHILE => 1, 267 /* T_YIELD */ => 1
|
||||
),
|
||||
self::MACRO_INCDEC => array(
|
||||
\T_WHILE => 1, \T_YIELD => 1, \T_YIELD_FROM => 1
|
||||
],
|
||||
self::MACRO_INCDEC => [
|
||||
\T_INC => 1, \T_DEC => 1
|
||||
),
|
||||
self::MACRO_UNARY => array(
|
||||
],
|
||||
self::MACRO_UNARY => [
|
||||
"!" => 1, "~" => 1, "-" => 1
|
||||
),
|
||||
self::MACRO_BINARY => array(
|
||||
],
|
||||
self::MACRO_BINARY => [
|
||||
\T_BOOLEAN_AND => 1, \T_BOOLEAN_OR => 1, \T_IS_GREATER_OR_EQUAL => 1,
|
||||
\T_IS_EQUAL => 1, \T_IS_IDENTICAL => 1, \T_IS_NOT_EQUAL => 1,
|
||||
\T_IS_NOT_IDENTICAL => 1, \T_IS_SMALLER_OR_EQUAL => 1, \T_LOGICAL_AND => 1,
|
||||
@ -117,36 +114,36 @@ class Tokenizer
|
||||
"*" => 1, "/" => 1, ">" => 1,
|
||||
"<" => 1, "^" => 1, "%" => 1,
|
||||
"&" => 1
|
||||
),
|
||||
self::MACRO_BOOLEAN => array(
|
||||
],
|
||||
self::MACRO_BOOLEAN => [
|
||||
\T_LOGICAL_OR => 1, \T_LOGICAL_XOR => 1,
|
||||
\T_BOOLEAN_AND => 1, \T_BOOLEAN_OR => 1,
|
||||
\T_LOGICAL_AND => 1
|
||||
),
|
||||
self::MACRO_MATH => array(
|
||||
],
|
||||
self::MACRO_MATH => [
|
||||
"+" => 1, "-" => 1, "*" => 1,
|
||||
"/" => 1, "^" => 1, "%" => 1,
|
||||
"&" => 1, "|" => 1
|
||||
),
|
||||
self::MACRO_COND => array(
|
||||
],
|
||||
self::MACRO_COND => [
|
||||
\T_IS_EQUAL => 1, \T_IS_IDENTICAL => 1, ">" => 1,
|
||||
"<" => 1, \T_SL => 1, \T_SR => 1,
|
||||
\T_IS_NOT_EQUAL => 1, \T_IS_NOT_IDENTICAL => 1, \T_IS_SMALLER_OR_EQUAL => 1,
|
||||
),
|
||||
self::MACRO_EQUALS => array(
|
||||
],
|
||||
self::MACRO_EQUALS => [
|
||||
\T_AND_EQUAL => 1, \T_DIV_EQUAL => 1, \T_MINUS_EQUAL => 1,
|
||||
\T_MOD_EQUAL => 1, \T_MUL_EQUAL => 1, \T_OR_EQUAL => 1,
|
||||
\T_PLUS_EQUAL => 1, \T_SL_EQUAL => 1, \T_SR_EQUAL => 1,
|
||||
\T_XOR_EQUAL => 1, '=' => 1,
|
||||
),
|
||||
self::MACRO_SCALAR => array(
|
||||
],
|
||||
self::MACRO_SCALAR => [
|
||||
\T_LNUMBER => 1,
|
||||
\T_DNUMBER => 1,
|
||||
\T_CONSTANT_ENCAPSED_STRING => 1
|
||||
)
|
||||
);
|
||||
]
|
||||
];
|
||||
|
||||
public static $description = array(
|
||||
public static array $description = [
|
||||
self::MACRO_STRING => 'string',
|
||||
self::MACRO_INCDEC => 'increment/decrement operator',
|
||||
self::MACRO_UNARY => 'unary operator',
|
||||
@ -156,26 +153,33 @@ class Tokenizer
|
||||
self::MACRO_COND => 'conditional operator',
|
||||
self::MACRO_EQUALS => 'equal operator',
|
||||
self::MACRO_SCALAR => 'scalar value'
|
||||
);
|
||||
];
|
||||
|
||||
/**
|
||||
* Special tokens
|
||||
* @var array
|
||||
*/
|
||||
private static $spec = array(
|
||||
private static array $spec = [
|
||||
'true' => 1,
|
||||
'false' => 1,
|
||||
'null' => 1,
|
||||
'TRUE' => 1,
|
||||
'FALSE' => 1,
|
||||
'NULL' => 1
|
||||
);
|
||||
];
|
||||
|
||||
private ?array $_next;
|
||||
private ?array $_prev;
|
||||
private ?array $_curr;
|
||||
|
||||
/**
|
||||
* @param $query
|
||||
* @param string $query
|
||||
*/
|
||||
public function __construct($query)
|
||||
public function __construct(string $query)
|
||||
{
|
||||
$this->_curr = null;
|
||||
$this->_next = null;
|
||||
$this->_prev = null;
|
||||
$tokens = array(-1 => array(\T_WHITESPACE, '', '', 1));
|
||||
$_tokens = token_get_all("<?php " . $query);
|
||||
$line = 1;
|
||||
@ -195,7 +199,7 @@ class Tokenizer
|
||||
$tokens[$i - 1][2] = $token[1];
|
||||
continue;
|
||||
} elseif ($token[0] === \T_DNUMBER) { // fix .1 and 1.
|
||||
if(strpos($token[1], '.') === 0) {
|
||||
if(str_starts_with($token[1], '.')) {
|
||||
$tokens[] = array(
|
||||
'.',
|
||||
'.',
|
||||
@ -239,9 +243,9 @@ class Tokenizer
|
||||
/**
|
||||
* Is incomplete mean some string not closed
|
||||
*
|
||||
* @return int
|
||||
* @return bool
|
||||
*/
|
||||
public function isIncomplete()
|
||||
public function isIncomplete(): bool
|
||||
{
|
||||
return ($this->quotes % 2) || ($this->tokens[$this->_max][0] === T_ENCAPSED_AND_WHITESPACE);
|
||||
}
|
||||
@ -252,9 +256,10 @@ class Tokenizer
|
||||
* @link http://php.net/manual/en/iterator.current.php
|
||||
* @return mixed Can return any type.
|
||||
*/
|
||||
public function current()
|
||||
public function current(): mixed
|
||||
{
|
||||
return $this->curr ? $this->curr[1] : null;
|
||||
$curr = $this->currToken();
|
||||
return $curr ? $curr[1] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -263,13 +268,13 @@ class Tokenizer
|
||||
* @link http://php.net/manual/en/iterator.next.php
|
||||
* @return Tokenizer
|
||||
*/
|
||||
public function next()
|
||||
public function next(): static
|
||||
{
|
||||
if ($this->p > $this->_max) {
|
||||
return $this;
|
||||
}
|
||||
$this->p++;
|
||||
unset($this->prev, $this->curr, $this->next);
|
||||
$this->cleanTokenCache();
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -277,10 +282,10 @@ class Tokenizer
|
||||
* Check token type. If token type is one of expected types return true. Otherwise return false
|
||||
*
|
||||
* @param array $expects
|
||||
* @param string|int $token
|
||||
* @param int|string $token
|
||||
* @return bool
|
||||
*/
|
||||
private function _valid($expects, $token)
|
||||
private function _valid(array $expects, int|string $token): bool
|
||||
{
|
||||
foreach ($expects as $expect) {
|
||||
if (is_string($expect) || $expect < 1000) {
|
||||
@ -300,13 +305,13 @@ class Tokenizer
|
||||
/**
|
||||
* If the next token is a valid one, move the position of cursor one step forward. Otherwise throws an exception.
|
||||
* @param array $tokens
|
||||
* @throws UnexpectedTokenException
|
||||
* @return mixed
|
||||
* @throws UnexpectedTokenException
|
||||
*/
|
||||
public function _next($tokens)
|
||||
public function _next(array $tokens): void
|
||||
{
|
||||
$this->next();
|
||||
if (!$this->curr) {
|
||||
if (!$this->currToken()) {
|
||||
throw new UnexpectedTokenException($this, $tokens);
|
||||
}
|
||||
if ($tokens) {
|
||||
@ -323,7 +328,7 @@ class Tokenizer
|
||||
* Fetch next specified token or throw an exception
|
||||
* @return mixed
|
||||
*/
|
||||
public function getNext( /*int|string $token1, int|string $token2, ... */)
|
||||
public function getNext( /*int|string $token1, int|string $token2, ... */): mixed
|
||||
{
|
||||
$this->_next(func_get_args());
|
||||
return $this->current();
|
||||
@ -333,9 +338,10 @@ class Tokenizer
|
||||
* @param $token
|
||||
* @return bool
|
||||
*/
|
||||
public function isNextToken($token)
|
||||
public function isNextToken($token): bool
|
||||
{
|
||||
return $this->next ? $this->next[1] == $token : false;
|
||||
$next = $this->nextToken();
|
||||
return $next && $next[1] == $token;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -343,10 +349,11 @@ class Tokenizer
|
||||
* @return mixed
|
||||
* @throws UnexpectedTokenException
|
||||
*/
|
||||
public function getAndNext( /* $token1, ... */)
|
||||
public function getAndNext( /* $token1, ... */): mixed
|
||||
{
|
||||
if ($this->curr) {
|
||||
$cur = $this->curr[1];
|
||||
$curr = $this->currToken();
|
||||
if ($curr) {
|
||||
$cur = $curr[1];
|
||||
$this->next();
|
||||
return $cur;
|
||||
} else {
|
||||
@ -359,9 +366,10 @@ class Tokenizer
|
||||
* @param $token1
|
||||
* @return bool
|
||||
*/
|
||||
public function isNext($token1 /*, ...*/)
|
||||
public function isNext($token1 /*, ...*/): bool
|
||||
{
|
||||
return $this->next && $this->_valid(func_get_args(), $this->next[0]);
|
||||
$next = $this->nextToken();
|
||||
return $next && $this->_valid(func_get_args(), $next[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -369,9 +377,10 @@ class Tokenizer
|
||||
* @param $token1
|
||||
* @return bool
|
||||
*/
|
||||
public function is($token1 /*, ...*/)
|
||||
public function is($token1 /*, ...*/): bool
|
||||
{
|
||||
return $this->curr && $this->_valid(func_get_args(), $this->curr[0]);
|
||||
$curr = $this->currToken();
|
||||
return $curr && $this->_valid(func_get_args(), $curr[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -379,22 +388,24 @@ class Tokenizer
|
||||
* @param $token1
|
||||
* @return bool
|
||||
*/
|
||||
public function isPrev($token1 /*, ...*/)
|
||||
public function isPrev($token1 /*, ...*/): bool
|
||||
{
|
||||
return $this->prev && $this->_valid(func_get_args(), $this->prev[0]);
|
||||
$prev = $this->prevToken();
|
||||
return $prev && $this->_valid(func_get_args(), $prev[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get specified token
|
||||
*
|
||||
* @param string|int $token1
|
||||
* @throws UnexpectedTokenException
|
||||
* @param int|string $token1
|
||||
* @return mixed
|
||||
*@throws UnexpectedTokenException
|
||||
*/
|
||||
public function get($token1 /*, $token2 ...*/)
|
||||
public function get(int|string $token1 /*, $token2 ...*/): mixed
|
||||
{
|
||||
if ($this->curr && $this->_valid(func_get_args(), $this->curr[0])) {
|
||||
return $this->curr[1];
|
||||
$curr = $this->currToken();
|
||||
if ($curr && $this->_valid(func_get_args(), $curr[0])) {
|
||||
return $curr[1];
|
||||
} else {
|
||||
throw new UnexpectedTokenException($this, func_get_args());
|
||||
}
|
||||
@ -404,21 +415,21 @@ class Tokenizer
|
||||
* Step back
|
||||
* @return Tokenizer
|
||||
*/
|
||||
public function back()
|
||||
public function back(): static
|
||||
{
|
||||
if ($this->p === 0) {
|
||||
return $this;
|
||||
}
|
||||
$this->p--;
|
||||
unset($this->prev, $this->curr, $this->next);
|
||||
$this->cleanTokenCache();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $token1
|
||||
* @param int|string $token1
|
||||
* @return bool
|
||||
*/
|
||||
public function hasBackList($token1 /*, $token2 ...*/)
|
||||
public function hasBackList(int|string $token1 /*, $token2 ...*/): bool
|
||||
{
|
||||
$tokens = func_get_args();
|
||||
$c = $this->p;
|
||||
@ -431,27 +442,38 @@ class Tokenizer
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy load properties
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($key)
|
||||
public function prevToken(): mixed
|
||||
{
|
||||
switch ($key) {
|
||||
case 'curr':
|
||||
return $this->curr = ($this->p <= $this->_max) ? $this->tokens[$this->p] : null;
|
||||
case 'next':
|
||||
return $this->next = ($this->p + 1 <= $this->_max) ? $this->tokens[$this->p + 1] : null;
|
||||
case 'prev':
|
||||
return $this->prev = $this->p ? $this->tokens[$this->p - 1] : null;
|
||||
default:
|
||||
return $this->$key = null;
|
||||
if ($this->_prev) {
|
||||
return $this->_prev;
|
||||
}
|
||||
return $this->_prev = $this->p ? $this->tokens[$this->p - 1] : null;
|
||||
}
|
||||
|
||||
public function count()
|
||||
public function currToken(): mixed
|
||||
{
|
||||
if ($this->_curr !== null) {
|
||||
return $this->_curr;
|
||||
}
|
||||
return $this->_curr = ($this->p <= $this->_max) ? $this->tokens[$this->p] : null;
|
||||
}
|
||||
|
||||
public function nextToken(): mixed
|
||||
{
|
||||
if ($this->_next) {
|
||||
return $this->_next;
|
||||
}
|
||||
return $this->_next = ($this->p + 1 <= $this->_max) ? $this->tokens[$this->p + 1] : null;
|
||||
}
|
||||
|
||||
protected function cleanTokenCache(): void
|
||||
{
|
||||
$this->_prev = null;
|
||||
$this->_curr = null;
|
||||
$this->_next = null;
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
return $this->_max;
|
||||
}
|
||||
@ -460,9 +482,10 @@ class Tokenizer
|
||||
* Return the key of the current element
|
||||
* @return mixed scalar on success, or null on failure.
|
||||
*/
|
||||
public function key()
|
||||
public function key(): mixed
|
||||
{
|
||||
return $this->curr ? $this->curr[0] : null;
|
||||
$curr = $this->currToken();
|
||||
return $curr ? $curr[0] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -470,18 +493,18 @@ class Tokenizer
|
||||
* @return boolean The return value will be casted to boolean and then evaluated.
|
||||
* Returns true on success or false on failure.
|
||||
*/
|
||||
public function valid()
|
||||
public function valid(): bool
|
||||
{
|
||||
return (bool)$this->curr;
|
||||
return (bool)$this->currToken();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get token name
|
||||
* @static
|
||||
* @param int|string $token
|
||||
* @return string
|
||||
* @param mixed $token
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getName($token)
|
||||
public static function getName(mixed $token): ?string
|
||||
{
|
||||
if (is_string($token)) {
|
||||
return $token;
|
||||
@ -500,10 +523,11 @@ class Tokenizer
|
||||
* @throws UnexpectedTokenException
|
||||
* @return Tokenizer
|
||||
*/
|
||||
public function skip( /*$token1, $token2, ...*/)
|
||||
public function skip( /*$token1, $token2, ...*/): static
|
||||
{
|
||||
if (func_num_args()) {
|
||||
if ($this->curr && $this->_valid(func_get_args(), $this->curr[0])) {
|
||||
$curr = $this->currToken();
|
||||
if ($curr && $this->_valid(func_get_args(), $curr[0])) {
|
||||
$this->next();
|
||||
return $this;
|
||||
} else {
|
||||
@ -521,9 +545,10 @@ class Tokenizer
|
||||
* @param int|string $token1
|
||||
* @return Tokenizer
|
||||
*/
|
||||
public function skipIf($token1 /*, $token2, ...*/)
|
||||
public function skipIf(int|string $token1 /*, $token2, ...*/): static
|
||||
{
|
||||
if ($this->curr && $this->_valid(func_get_args(), $this->curr[0])) {
|
||||
$curr = $this->currToken();
|
||||
if ($curr && $this->_valid(func_get_args(), $curr[0])) {
|
||||
$this->next();
|
||||
}
|
||||
return $this;
|
||||
@ -536,9 +561,10 @@ class Tokenizer
|
||||
* @return Tokenizer
|
||||
* @throws UnexpectedTokenException
|
||||
*/
|
||||
public function need($token1 /*, $token2, ...*/)
|
||||
public function need(int|string $token1 /*, $token2, ...*/): static
|
||||
{
|
||||
if ($this->curr && $this->_valid(func_get_args(), $this->curr[0])) {
|
||||
$curr = $this->currToken();
|
||||
if ($curr && $this->_valid(func_get_args(), $curr[0])) {
|
||||
return $this;
|
||||
} else {
|
||||
throw new UnexpectedTokenException($this, func_get_args());
|
||||
@ -551,7 +577,7 @@ class Tokenizer
|
||||
* @param int $after count tokens after current token
|
||||
* @return array
|
||||
*/
|
||||
public function getSnippet($before = 0, $after = 0)
|
||||
public function getSnippet(int $before = 0, int $after = 0): array
|
||||
{
|
||||
$from = 0;
|
||||
$to = $this->p;
|
||||
@ -594,7 +620,7 @@ class Tokenizer
|
||||
* @param int $after
|
||||
* @return string
|
||||
*/
|
||||
public function getSnippetAsString($before = 0, $after = 0)
|
||||
public function getSnippetAsString(int $before = 0, int $after = 0): string
|
||||
{
|
||||
$str = "";
|
||||
foreach ($this->getSnippet($before, $after) as $token) {
|
||||
@ -607,7 +633,7 @@ class Tokenizer
|
||||
* Check if current is special value: true, TRUE, false, FALSE, null, NULL
|
||||
* @return bool
|
||||
*/
|
||||
public function isSpecialVal()
|
||||
public function isSpecialVal(): bool
|
||||
{
|
||||
return isset(self::$spec[$this->current()]);
|
||||
}
|
||||
@ -616,7 +642,7 @@ class Tokenizer
|
||||
* Check if the token is last
|
||||
* @return bool
|
||||
*/
|
||||
public function isLast()
|
||||
public function isLast(): bool
|
||||
{
|
||||
return $this->p === $this->_max;
|
||||
}
|
||||
@ -624,10 +650,10 @@ class Tokenizer
|
||||
/**
|
||||
* Move pointer to the end
|
||||
*/
|
||||
public function end()
|
||||
public function end(): static
|
||||
{
|
||||
$this->p = $this->_max;
|
||||
unset($this->prev, $this->curr, $this->next);
|
||||
$this->cleanTokenCache();
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -635,23 +661,26 @@ class Tokenizer
|
||||
* Return line number of the current token
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLine()
|
||||
public function getLine(): mixed
|
||||
{
|
||||
return $this->curr ? $this->curr[3] : $this->_last_no;
|
||||
$curr = $this->currToken();
|
||||
return $curr ? $curr[3] : $this->_last_no;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is current token whitespaced, means previous token has whitespace characters
|
||||
* @return bool
|
||||
*/
|
||||
public function isWhiteSpaced()
|
||||
public function isWhiteSpaced(): bool
|
||||
{
|
||||
return $this->prev ? (bool)$this->prev[2] : false;
|
||||
$prev = $this->prevToken();
|
||||
return $prev && $prev[2];
|
||||
}
|
||||
|
||||
public function getWhitespace()
|
||||
{
|
||||
return $this->curr ? $this->curr[2] : false;
|
||||
$curr = $this->currToken();
|
||||
return $curr ? $curr[2] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -659,10 +688,10 @@ class Tokenizer
|
||||
* @param int $p
|
||||
* @return $this
|
||||
*/
|
||||
public function seek($p)
|
||||
public function seek(int $p): static
|
||||
{
|
||||
$this->p = $p;
|
||||
unset($this->prev, $this->curr, $this->next);
|
||||
$this->cleanTokenCache();
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ class TestCase extends \PHPUnit\Framework\TestCase
|
||||
return FENOM_RESOURCES . '/compile';
|
||||
}
|
||||
|
||||
public function setUp()
|
||||
public function setUp(): void
|
||||
{
|
||||
if (!file_exists($this->getCompilePath())) {
|
||||
mkdir($this->getCompilePath(), 0777, true);
|
||||
@ -89,7 +89,7 @@ class TestCase extends \PHPUnit\Framework\TestCase
|
||||
|
||||
public static function inlineFunction($params)
|
||||
{
|
||||
return isset($params["text"]) ? $params["text"] : "";
|
||||
return $params["text"] ?? "";
|
||||
}
|
||||
|
||||
public static function blockFunction($params, $text)
|
||||
@ -97,7 +97,7 @@ class TestCase extends \PHPUnit\Framework\TestCase
|
||||
return $text;
|
||||
}
|
||||
|
||||
public static function setUpBeforeClass()
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
if (!file_exists(FENOM_RESOURCES . '/template')) {
|
||||
mkdir(FENOM_RESOURCES . '/template', 0777, true);
|
||||
|
@ -1,11 +1,7 @@
|
||||
<?php
|
||||
|
||||
require(__DIR__ . "/../src/Fenom.php");
|
||||
Fenom::registerAutoload();
|
||||
|
||||
if(!class_exists('\PHPUnit_Framework_TestCase') && class_exists('\PHPUnit\Framework\TestCase')) {
|
||||
class_alias('\PHPUnit\Framework\TestCase', '\PHPUnit_Framework_TestCase');
|
||||
}
|
||||
//Fenom::registerAutoload();
|
||||
|
||||
define('FENOM_RESOURCES', __DIR__ . "/resources");
|
||||
|
||||
|
@ -45,7 +45,7 @@ class TokenizerTest extends TestCase
|
||||
' ',
|
||||
1
|
||||
),
|
||||
$tokens->curr
|
||||
$tokens->currToken()
|
||||
);
|
||||
$this->assertSame("resolve", $tokens->getNext($tokens::MACRO_UNARY, T_STRING));
|
||||
|
||||
@ -106,7 +106,6 @@ class TokenizerTest extends TestCase
|
||||
$this->assertSame($tokens, $tokens->next());
|
||||
$tokens->p = -1000;
|
||||
$this->assertSame($tokens, $tokens->back());
|
||||
$this->assertNull($tokens->undef);
|
||||
}
|
||||
|
||||
public function testFixFloats() {
|
||||
|
Loading…
Reference in New Issue
Block a user