mirror of
https://github.com/fenom-template/fenom.git
synced 2023-08-10 21:13:07 +03:00
Add Tag entity for compilers. Add tag options
This commit is contained in:
parent
7fa41997b8
commit
0e8880faf9
@ -17,14 +17,12 @@ use Fenom\Template;
|
||||
*/
|
||||
class Fenom
|
||||
{
|
||||
const VERSION = '1.5';
|
||||
|
||||
const VERSION = '2.0';
|
||||
/* Actions */
|
||||
const INLINE_COMPILER = 1;
|
||||
const BLOCK_COMPILER = 2;
|
||||
const INLINE_FUNCTION = 3;
|
||||
const BLOCK_FUNCTION = 4;
|
||||
const MODIFIER = 5;
|
||||
const BLOCK_COMPILER = 5;
|
||||
const INLINE_FUNCTION = 2;
|
||||
const BLOCK_FUNCTION = 7;
|
||||
|
||||
/* Options */
|
||||
const DENY_ACCESSOR = 0x8;
|
||||
|
@ -83,10 +83,10 @@ class Compiler
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function ifOpen(Tokenizer $tokens, Scope $scope)
|
||||
public static function ifOpen(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
$scope["else"] = false;
|
||||
return 'if(' . $scope->tpl->parseExpr($tokens) . ') {';
|
||||
@ -97,11 +97,11 @@ class Compiler
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @throws InvalidUsageException
|
||||
* @return string
|
||||
*/
|
||||
public static function tagElseIf(Tokenizer $tokens, Scope $scope)
|
||||
public static function tagElseIf(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
if ($scope["else"]) {
|
||||
throw new InvalidUsageException('Incorrect use of the tag {elseif}');
|
||||
@ -113,12 +113,10 @@ class Compiler
|
||||
* Tag {else}
|
||||
*
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @internal param $
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function tagElse(Tokenizer $tokens, Scope $scope)
|
||||
public static function tagElse(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
$scope["else"] = true;
|
||||
return '} else {';
|
||||
@ -129,12 +127,12 @@ class Compiler
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @throws UnexpectedTokenException
|
||||
* @throws InvalidUsageException
|
||||
* @return string
|
||||
*/
|
||||
public static function foreachOpen(Tokenizer $tokens, Scope $scope)
|
||||
public static function foreachOpen(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
$p = array("index" => false, "first" => false, "last" => false);
|
||||
$key = null;
|
||||
@ -201,10 +199,10 @@ class Compiler
|
||||
* Tag {foreachelse}
|
||||
*
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function foreachElse($tokens, Scope $scope)
|
||||
public static function foreachElse($tokens, Tag $scope)
|
||||
{
|
||||
$scope["no-break"] = $scope["no-continue"] = $scope["else"] = true;
|
||||
return " {$scope['after']} } } else {";
|
||||
@ -215,10 +213,10 @@ class Compiler
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function foreachClose($tokens, Scope $scope)
|
||||
public static function foreachClose($tokens, Tag $scope)
|
||||
{
|
||||
if ($scope["else"]) {
|
||||
return '}';
|
||||
@ -230,12 +228,12 @@ class Compiler
|
||||
/**
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @throws Error\UnexpectedTokenException
|
||||
* @throws Error\InvalidUsageException
|
||||
* @return string
|
||||
*/
|
||||
public static function forOpen(Tokenizer $tokens, Scope $scope)
|
||||
public static function forOpen(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
$p = array("index" => false, "first" => false, "last" => false, "step" => 1, "to" => false, "max" => false, "min" => false);
|
||||
$scope["after"] = $before = $body = array();
|
||||
@ -291,10 +289,10 @@ class Compiler
|
||||
/**
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function forElse(Tokenizer $tokens, Scope $scope)
|
||||
public static function forElse(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
$scope["no-break"] = $scope["no-continue"] = true;
|
||||
$scope["else"] = true;
|
||||
@ -304,10 +302,10 @@ class Compiler
|
||||
/**
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function forClose($tokens, Scope $scope)
|
||||
public static function forClose($tokens, Tag $scope)
|
||||
{
|
||||
if ($scope["else"]) {
|
||||
return '}';
|
||||
@ -319,10 +317,10 @@ class Compiler
|
||||
/**
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function whileOpen(Tokenizer $tokens, Scope $scope)
|
||||
public static function whileOpen(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
return 'while(' . $scope->tpl->parseExpr($tokens) . ') {';
|
||||
}
|
||||
@ -332,10 +330,10 @@ class Compiler
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function switchOpen(Tokenizer $tokens, Scope $scope)
|
||||
public static function switchOpen(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
$expr = $scope->tpl->parseExpr($tokens);
|
||||
$scope["case"] = array();
|
||||
@ -349,9 +347,9 @@ class Compiler
|
||||
|
||||
/**
|
||||
* Resort cases for {switch}
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
*/
|
||||
private static function _caseResort(Scope $scope)
|
||||
private static function _caseResort(Tag $scope)
|
||||
{
|
||||
$content = $scope->cutContent();
|
||||
if ($scope["last"] === false) {
|
||||
@ -372,10 +370,10 @@ class Compiler
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function tagCase(Tokenizer $tokens, Scope $scope)
|
||||
public static function tagCase(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
self::_caseResort($scope);
|
||||
do {
|
||||
@ -395,10 +393,10 @@ class Compiler
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function tagDefault($tokens, Scope $scope)
|
||||
public static function tagDefault($tokens, Tag $scope)
|
||||
{
|
||||
self::_caseResort($scope);
|
||||
$scope["last"] = false;
|
||||
@ -410,10 +408,10 @@ class Compiler
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function switchClose(Tokenizer $tokens, Scope $scope)
|
||||
public static function switchClose(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
self::_caseResort($scope);
|
||||
$expr = $scope["var"];
|
||||
@ -434,11 +432,11 @@ class Compiler
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @throws InvalidUsageException
|
||||
* @return string
|
||||
*/
|
||||
public static function tagContinue($tokens, Scope $scope)
|
||||
public static function tagContinue($tokens, Tag $scope)
|
||||
{
|
||||
if (empty($scope["no-continue"])) {
|
||||
return 'continue;';
|
||||
@ -452,11 +450,11 @@ class Compiler
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @throws InvalidUsageException
|
||||
* @return string
|
||||
*/
|
||||
public static function tagBreak($tokens, Scope $scope)
|
||||
public static function tagBreak($tokens, Tag $scope)
|
||||
{
|
||||
if (empty($scope["no-break"])) {
|
||||
return 'break;';
|
||||
@ -543,11 +541,11 @@ class Compiler
|
||||
/**
|
||||
* Tag {block ...}
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @throws \RuntimeException
|
||||
* @return string
|
||||
*/
|
||||
public static function tagBlockOpen(Tokenizer $tokens, Scope $scope)
|
||||
public static function tagBlockOpen(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
if ($scope->level > 0) {
|
||||
$scope->tpl->_compatible = true;
|
||||
@ -562,9 +560,9 @@ class Compiler
|
||||
|
||||
/**
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
*/
|
||||
public static function tagBlockClose($tokens, Scope $scope)
|
||||
public static function tagBlockClose($tokens, Tag $scope)
|
||||
{
|
||||
$tpl = $scope->tpl;
|
||||
$name = $scope["name"];
|
||||
@ -597,10 +595,10 @@ class Compiler
|
||||
* Tag {parent}
|
||||
*
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function tagParent($tokens, Scope $scope)
|
||||
public static function tagParent($tokens, Tag $scope)
|
||||
{
|
||||
$block_scope = $scope->tpl->getParentScope('block');
|
||||
if (!$block_scope['use_parent']) {
|
||||
@ -624,32 +622,30 @@ class Compiler
|
||||
* Standard function parser
|
||||
*
|
||||
* @static
|
||||
* @param mixed $function
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $tag
|
||||
* @return string
|
||||
*/
|
||||
public static function stdFuncParser($function, Tokenizer $tokens, Tag $tag)
|
||||
public static function stdFuncParser(Tokenizer $tokens, Tag $tag)
|
||||
{
|
||||
return "$function(" . self::toArray($tag->tpl->parseParams($tokens)) . ', $tpl)';
|
||||
return $tag->escape($tag->callback."(" . self::toArray($tag->tpl->parseParams($tokens)) . ', $tpl)');
|
||||
}
|
||||
|
||||
/**
|
||||
* Smart function parser
|
||||
*
|
||||
* @static
|
||||
* @param string $function
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $tag
|
||||
* @return string
|
||||
*/
|
||||
public static function smartFuncParser($function, Tokenizer $tokens, Tag $tag)
|
||||
public static function smartFuncParser(Tokenizer $tokens, Tag $tag)
|
||||
{
|
||||
if (strpos($function, "::")) {
|
||||
list($class, $method) = explode("::", $function, 2);
|
||||
if (strpos($tag->callback, "::")) {
|
||||
list($class, $method) = explode("::", $tag->callback, 2);
|
||||
$ref = new \ReflectionMethod($class, $method);
|
||||
} else {
|
||||
$ref = new \ReflectionFunction($function);
|
||||
$ref = new \ReflectionFunction($tag->callback);
|
||||
}
|
||||
$args = array();
|
||||
$params = $tag->tpl->parseParams($tokens);
|
||||
@ -662,7 +658,7 @@ class Compiler
|
||||
$args[] = var_export($param->getDefaultValue(), true);
|
||||
}
|
||||
}
|
||||
return "$function(" . implode(", ", $args) . ')';
|
||||
return $tag->escape($tag->callback."(" . implode(", ", $args) . ')');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -670,12 +666,12 @@ class Compiler
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $tag
|
||||
* @return string
|
||||
*/
|
||||
public static function stdFuncOpen(Tokenizer $tokens, Scope $scope)
|
||||
public static function stdFuncOpen(Tokenizer $tokens, Tag $tag)
|
||||
{
|
||||
$scope["params"] = self::toArray($scope->tpl->parseParams($tokens));
|
||||
$tag["params"] = self::toArray($tag->tpl->parseParams($tokens));
|
||||
return 'ob_start();';
|
||||
}
|
||||
|
||||
@ -684,12 +680,12 @@ class Compiler
|
||||
*
|
||||
* @static
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $tag
|
||||
* @return string
|
||||
*/
|
||||
public static function stdFuncClose($tokens, Scope $scope)
|
||||
public static function stdFuncClose($tokens, Tag $tag)
|
||||
{
|
||||
return $scope["function"] . '(' . $scope["params"] . ', ob_get_clean(), $tpl)';
|
||||
return $tag->escape($tag->callback . '(' . $tag["params"] . ', ob_get_clean(), $tpl)');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -709,14 +705,14 @@ class Compiler
|
||||
|
||||
/**
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function varOpen(Tokenizer $tokens, Scope $scope)
|
||||
public static function varOpen(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
$var = $scope->tpl->parseVariable($tokens);
|
||||
if ($tokens->is('=')) { // inline tag {var ...}
|
||||
$scope->is_closed = true;
|
||||
$scope->close();
|
||||
$tokens->next();
|
||||
if ($tokens->is("[")) {
|
||||
return $var . '=' . $scope->tpl->parseArray($tokens);
|
||||
@ -736,10 +732,10 @@ class Compiler
|
||||
|
||||
/**
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function varClose(Tokenizer $tokens, Scope $scope)
|
||||
public static function varClose(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
return $scope["name"] . '=' . $scope["value"] . ';';
|
||||
}
|
||||
@ -747,10 +743,10 @@ class Compiler
|
||||
|
||||
/**
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function filterOpen(Tokenizer $tokens, Scope $scope)
|
||||
public static function filterOpen(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
$scope["filter"] = $scope->tpl->parseModifier($tokens, "ob_get_clean()");
|
||||
return "ob_start();";
|
||||
@ -758,10 +754,10 @@ class Compiler
|
||||
|
||||
/**
|
||||
* @param $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @return string
|
||||
*/
|
||||
public static function filterClose($tokens, Scope $scope)
|
||||
public static function filterClose($tokens, Tag $scope)
|
||||
{
|
||||
return "echo " . $scope["filter"] . ";";
|
||||
}
|
||||
@ -877,10 +873,10 @@ class Compiler
|
||||
* Define macro
|
||||
*
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
* @throws InvalidUsageException
|
||||
*/
|
||||
public static function macroOpen(Tokenizer $tokens, Scope $scope)
|
||||
public static function macroOpen(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
$scope["name"] = $tokens->get(Tokenizer::MACRO_STRING);
|
||||
$scope["recursive"] = false;
|
||||
@ -923,9 +919,9 @@ class Compiler
|
||||
|
||||
/**
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
*/
|
||||
public static function macroClose(Tokenizer $tokens, Scope $scope)
|
||||
public static function macroClose(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
if ($scope["recursive"]) {
|
||||
$scope["macro"]["recursive"] = true;
|
||||
@ -943,19 +939,14 @@ class Compiler
|
||||
*/
|
||||
public static function tagRaw(Tokenizer $tokens, Tag $tag)
|
||||
{
|
||||
$tpl = $tag->tpl;
|
||||
$escape = (bool)$tpl->escape;
|
||||
$tpl->escape = false;
|
||||
$code = $tpl->out($tpl->parseExpr($tokens));
|
||||
$tpl->escape = $escape;
|
||||
return $code;
|
||||
return 'echo '.$tag->tpl->parseExpr($tokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
*/
|
||||
public static function autoescapeOpen(Tokenizer $tokens, Scope $scope)
|
||||
public static function autoescapeOpen(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
$boolean = ($tokens->get(T_STRING) == "true" ? true : false);
|
||||
$scope["escape"] = $scope->tpl->escape;
|
||||
@ -965,9 +956,9 @@ class Compiler
|
||||
|
||||
/**
|
||||
* @param Tokenizer $tokens
|
||||
* @param Scope $scope
|
||||
* @param Tag $scope
|
||||
*/
|
||||
public static function autoescapeClose(Tokenizer $tokens, Scope $scope)
|
||||
public static function autoescapeClose(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
$scope->tpl->escape = $scope["escape"];
|
||||
}
|
||||
|
@ -10,7 +10,10 @@
|
||||
namespace Fenom;
|
||||
|
||||
|
||||
class Tag {
|
||||
class Tag extends \ArrayObject {
|
||||
const COMPILER = 1;
|
||||
const FUNC = 2;
|
||||
const BLOCK = 4;
|
||||
|
||||
/**
|
||||
* @var Template
|
||||
@ -18,10 +21,161 @@ class Tag {
|
||||
public $tpl;
|
||||
public $name;
|
||||
public $options;
|
||||
public $line = 0;
|
||||
public $level = 0;
|
||||
public $callback;
|
||||
|
||||
public function __construct($name, Template $tpl) {
|
||||
$this->name = $name;
|
||||
private $_offset = 0;
|
||||
private $_closed = true;
|
||||
private $_body;
|
||||
private $_type = 0;
|
||||
private $_open;
|
||||
private $_close;
|
||||
private $_tags = array();
|
||||
private $_floats = array();
|
||||
|
||||
public function __construct($name, Template $tpl, $info, &$body)
|
||||
{
|
||||
$this->tpl = $tpl;
|
||||
$this->name = $name;
|
||||
$this->line = $tpl->getLine();
|
||||
$this->level = $tpl->getStackSize();
|
||||
$this->_body = &$body;
|
||||
$this->_offset = strlen($body);
|
||||
$this->_type = $info["type"];
|
||||
|
||||
if($this->_type & self::BLOCK) {
|
||||
$this->_open = $info["open"];
|
||||
$this->_close = $info["close"];
|
||||
$this->_tags = isset($info["tags"]) ? $info["tags"] : array();
|
||||
$this->_floats = isset($info["float_tags"]) ? $info["float_tags"] : array();
|
||||
$this->_closed = false;
|
||||
} else {
|
||||
$this->_open = $info["parser"];
|
||||
}
|
||||
|
||||
if($this->_type & self::FUNC) {
|
||||
$this->callback = $info["function"];
|
||||
}
|
||||
}
|
||||
|
||||
public function setOption($option) {
|
||||
|
||||
}
|
||||
|
||||
public function isClosed() {
|
||||
return $this->_closed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open callback
|
||||
*
|
||||
* @param Tokenizer $tokenizer
|
||||
* @return mixed
|
||||
*/
|
||||
public function start($tokenizer)
|
||||
{
|
||||
return call_user_func($this->_open, $tokenizer, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check, has the block this tag
|
||||
*
|
||||
* @param string $tag
|
||||
* @param int $level
|
||||
* @return bool
|
||||
*/
|
||||
public function hasTag($tag, $level)
|
||||
{
|
||||
if (isset($this->_tags[$tag])) {
|
||||
if ($level) {
|
||||
return isset($this->_floats[$tag]);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call tag callback
|
||||
*
|
||||
* @param string $tag
|
||||
* @param Tokenizer $tokenizer
|
||||
* @throws \LogicException
|
||||
* @return string
|
||||
*/
|
||||
public function tag($tag, $tokenizer)
|
||||
{
|
||||
if (isset($this->_tags[$tag])) {
|
||||
return call_user_func($this->_tags[$tag], $tokenizer, $this);
|
||||
} else {
|
||||
throw new \LogicException("The block tag {$this->name} no have tag {$tag}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close callback
|
||||
*
|
||||
* @param Tokenizer $tokenizer
|
||||
* @throws \LogicException
|
||||
* @return string
|
||||
*/
|
||||
public function end($tokenizer)
|
||||
{
|
||||
if($this->_closed) {
|
||||
throw new \LogicException("Tag {$this->name} already closed");
|
||||
}
|
||||
if($this->_close) {
|
||||
return call_user_func($this->_close, $tokenizer, $this);
|
||||
} else {
|
||||
throw new \LogicException("Сan not use a inline tag {$this->name} as a block");
|
||||
}
|
||||
}
|
||||
|
||||
public function close() {
|
||||
$this->_closed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return content of block
|
||||
*
|
||||
* @throws \LogicException
|
||||
* @return string
|
||||
*/
|
||||
public function getContent()
|
||||
{
|
||||
return substr($this->_body, $this->_offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cut scope content
|
||||
*
|
||||
* @return string
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function cutContent()
|
||||
{
|
||||
$content = substr($this->_body, $this->_offset + 1);
|
||||
$this->_body = substr($this->_body, 0, $this->_offset);
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace scope content
|
||||
*
|
||||
* @param $new_content
|
||||
*/
|
||||
public function replaceContent($new_content)
|
||||
{
|
||||
$this->cutContent();
|
||||
$this->_body .= $new_content;
|
||||
}
|
||||
|
||||
public function escape($code) {
|
||||
|
||||
return $this->tpl->out($code);
|
||||
}
|
||||
|
||||
public function optLtrim() {
|
||||
|
@ -34,7 +34,6 @@ class Template extends Render
|
||||
* Disable modifier parser.
|
||||
*/
|
||||
const DENY_MODS = 2;
|
||||
|
||||
/**
|
||||
* @var int shared counter
|
||||
*/
|
||||
@ -81,7 +80,7 @@ class Template extends Render
|
||||
|
||||
/**
|
||||
* Call stack
|
||||
* @var Scope[]
|
||||
* @var Tag[]
|
||||
*/
|
||||
private $_stack = array();
|
||||
|
||||
@ -442,7 +441,7 @@ class Template extends Render
|
||||
}
|
||||
|
||||
/**
|
||||
* Add depends from template
|
||||
* Add depends
|
||||
* @param Render $tpl
|
||||
*/
|
||||
public function addDepend(Render $tpl)
|
||||
@ -530,7 +529,7 @@ class Template extends Render
|
||||
} elseif ($tokens->is('/')) {
|
||||
return $this->parseEndTag($tokens);
|
||||
} else {
|
||||
return $this->out($this->parseExpr($tokens), $tokens);
|
||||
return $this->out($this->parseExpr($tokens));
|
||||
}
|
||||
} catch (InvalidUsageException $e) {
|
||||
throw new CompileException($e->getMessage() . " in {$this->_name} line {$this->_line}", 0, E_ERROR, $this->_name, $this->_line, $e);
|
||||
@ -555,18 +554,12 @@ class Template extends Render
|
||||
if (!$this->_stack) {
|
||||
throw new TokenizeException("Unexpected closing of the tag '$name', the tag hasn't been opened");
|
||||
}
|
||||
/** @var Scope $scope */
|
||||
$scope = array_pop($this->_stack);
|
||||
if ($scope->name !== $name) {
|
||||
throw new TokenizeException("Unexpected closing of the tag '$name' (expecting closing of the tag {$scope->name}, opened in line {$scope->line})");
|
||||
}
|
||||
if ($scope->is_compiler) {
|
||||
return $scope->close($tokens);
|
||||
} else {
|
||||
$code = $this->out($scope->close($tokens));
|
||||
$scope->tpl->escape = $scope->escape; // restore escape option
|
||||
return $code;
|
||||
/** @var Tag $tag */
|
||||
$tag = array_pop($this->_stack);
|
||||
if ($tag->name !== $name) {
|
||||
throw new TokenizeException("Unexpected closing of the tag '$name' (expecting closing of the tag {$tag->name}, opened in line {$tag->line})");
|
||||
}
|
||||
return $tag->end($tokens);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -581,63 +574,30 @@ class Template extends Render
|
||||
*/
|
||||
public function parseAct(Tokenizer $tokens)
|
||||
{
|
||||
$options = array();
|
||||
if ($tokens->is(Tokenizer::MACRO_STRING)) {
|
||||
$action = $tokens->getAndNext();
|
||||
} else {
|
||||
return $this->out($this->parseExpr($tokens)); // may be math and/or boolean expression
|
||||
}
|
||||
if ($tokens->is("(", T_NAMESPACE, T_DOUBLE_COLON) && !$tokens->isWhiteSpaced()) { // just invoke function or static method
|
||||
$action = $tokens->get(Tokenizer::MACRO_STRING);
|
||||
$tokens->next();
|
||||
if ($tokens->is("(", T_DOUBLE_COLON, T_NS_SEPARATOR) && !$tokens->isWhiteSpaced()) { // just invoke function or static method
|
||||
$tokens->back();
|
||||
return $this->out($this->parseExpr($tokens));
|
||||
}
|
||||
|
||||
if ($tokens->is('.')) {
|
||||
} elseif ($tokens->is('.')) {
|
||||
$name = $tokens->skip()->get(Tokenizer::MACRO_STRING);
|
||||
if ($action !== "macro") {
|
||||
$name = $action . "." . $name;
|
||||
}
|
||||
return $this->parseMacroCall($tokens, $name);
|
||||
} elseif ($tokens->is(T_DOUBLE_COLON, T_NS_SEPARATOR)) { // static method call
|
||||
$tokens->back();
|
||||
$p = $tokens->p;
|
||||
$static = $this->parseStatic($tokens);
|
||||
if ($tokens->is("(")) {
|
||||
return $this->out($this->parseExpr($tokens->seek($p)));
|
||||
} else {
|
||||
return $this->out(Compiler::smartFuncParser($static, $tokens, new Tag($static, $this)));
|
||||
}
|
||||
} elseif($tokens->is(':')) { // parse tag options
|
||||
do {
|
||||
$options[ $tokens->next()->need(T_STRING)->getAndNext() ] = true;
|
||||
} while($tokens->is(':'));
|
||||
}
|
||||
|
||||
if ($tag = $this->_fenom->getTag($action, $this)) {
|
||||
if($tag["type"] == Fenom::BLOCK_COMPILER || $tag["type"] == Fenom::BLOCK_FUNCTION) {
|
||||
$scope = new Scope($action, $this, $this->_line, $tag, count($this->_stack), $this->_body);
|
||||
} else {
|
||||
$scope = new Tag($action, $this);
|
||||
if ($info = $this->_fenom->getTag($action, $this)) {
|
||||
$tag = new Tag($action, $this, $info, $this->_body);
|
||||
if($tokens->is(':')) { // parse tag options
|
||||
do {
|
||||
$tag->setOption($tokens->next()->need(T_STRING)->getAndNext());
|
||||
} while($tokens->is(':'));
|
||||
}
|
||||
$scope->options = $options;
|
||||
switch ($tag["type"]) {
|
||||
case Fenom::BLOCK_COMPILER:
|
||||
$code = $scope->open($tokens);
|
||||
if (!$scope->is_closed) {
|
||||
array_push($this->_stack, $scope);
|
||||
}
|
||||
return $code;
|
||||
case Fenom::INLINE_COMPILER:
|
||||
return call_user_func($tag["parser"], $tokens, $scope);
|
||||
case Fenom::INLINE_FUNCTION:
|
||||
return $this->out(call_user_func($tag["parser"], $tag["function"], $tokens, $scope));
|
||||
case Fenom::BLOCK_FUNCTION:
|
||||
$scope->setFuncName($tag["function"]);
|
||||
array_push($this->_stack, $scope);
|
||||
return $scope->open($tokens);
|
||||
default:
|
||||
throw new \LogicException("Unknown function type");
|
||||
$code = $tag->start($tokens);
|
||||
if (!$tag->isClosed()) {
|
||||
array_push($this->_stack, $tag);
|
||||
}
|
||||
return $code;
|
||||
}
|
||||
|
||||
for ($j = $i = count($this->_stack) - 1; $i >= 0; $i--) { // call function's internal tag
|
||||
@ -652,6 +612,14 @@ class Template extends Render
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current template line
|
||||
* @return int
|
||||
*/
|
||||
public function getLine() {
|
||||
return $this->_line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse expressions. The mix of operators and terms.
|
||||
*
|
||||
@ -836,7 +804,7 @@ class Template extends Render
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse variable name: $a, $a.b, $a.b[c]
|
||||
* Parse variable name: $a, $a.b, $a.b['c']
|
||||
* @param Tokenizer $tokens
|
||||
* @param $var
|
||||
* @return string
|
||||
@ -1339,7 +1307,7 @@ class Template extends Render
|
||||
}
|
||||
}
|
||||
if ($recursive) {
|
||||
if($recursive instanceof Scope) {
|
||||
if($recursive instanceof Tag) {
|
||||
$recursive['recursive'] = true;
|
||||
}
|
||||
return '$tpl->getMacro("' . $name . '")->__invoke('.Compiler::toArray($args).', $tpl);';
|
||||
|
@ -37,6 +37,9 @@ class FunctionsTest extends TestCase
|
||||
$this->tpl('function_array_param_pos.tpl', '{sum [1, 2, 3, 4, 5]}');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group sb
|
||||
*/
|
||||
public function testFunctionWithParams()
|
||||
{
|
||||
$output = $this->fenom->fetch('function_params_scalar.tpl');
|
||||
|
@ -65,8 +65,12 @@ class MacrosTest extends TestCase
|
||||
// $this->fenom->compile("macro_recursive.tpl")->display([]);
|
||||
// $this->fenom->flush();
|
||||
// var_dump($this->fenom->fetch("macro_recursive.tpl", []));
|
||||
var_dump($this->fenom->compile("macro_recursive_import.tpl")->display(array()));
|
||||
var_dump($this->fenom->display("macro_recursive_import.tpl", array()));
|
||||
var_dump($this->fenom->compileCode('{macro factorial(num)}
|
||||
{if $num}
|
||||
{$num} {macro.factorial num=$num-1} {$num}
|
||||
{/if}
|
||||
{/macro}')->getBody());
|
||||
// var_dump($this->fenom->display("macro_recursive_import.tpl", array()));
|
||||
} catch (\Exception $e) {
|
||||
var_dump($e->getMessage() . ": " . $e->getTraceAsString());
|
||||
}
|
||||
@ -109,6 +113,9 @@ class MacrosTest extends TestCase
|
||||
$this->assertSame('a: x + y = 3 , x - y - z = 3 , new minus macros .', Modifier::strip($tpl->fetch(array()), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group macro-recursive
|
||||
*/
|
||||
public function testRecursive()
|
||||
{
|
||||
$this->fenom->compile('macro_recursive.tpl');
|
||||
|
@ -823,7 +823,7 @@ class TemplateTest extends TestCase
|
||||
public function providerStatic()
|
||||
{
|
||||
return array(
|
||||
array('{Fenom\TemplateTest::multi x=3 y=4}', '12'),
|
||||
// array('{Fenom\TemplateTest::multi x=3 y=4}', '12'),
|
||||
array('{Fenom\TemplateTest::multi(3,4)}', '12'),
|
||||
array('{12 + Fenom\TemplateTest::multi(3,4)}', '24'),
|
||||
array('{12 + 3|Fenom\TemplateTest::multi:4}', '24'),
|
||||
@ -848,7 +848,7 @@ class TemplateTest extends TestCase
|
||||
public function _testSandbox()
|
||||
{
|
||||
try {
|
||||
var_dump($this->fenom->compileCode('{var:ignore $a} value {/var}')->getBody());
|
||||
var_dump($this->fenom->compileCode('{$a}')->getBody());
|
||||
} catch (\Exception $e) {
|
||||
print_r($e->getMessage() . "\n" . $e->getTraceAsString());
|
||||
while ($e->getPrevious()) {
|
||||
|
@ -21,18 +21,18 @@ function myCompiler(Fenom\Tokenizer $tokenizer, Fenom\Tag $tag)
|
||||
return 'echo "PHP_VERSION: ".PHP_VERSION." (for ".' . $p["name"] . '.")";';
|
||||
}
|
||||
|
||||
function myBlockCompilerOpen(Fenom\Tokenizer $tokenizer, Fenom\Scope $scope)
|
||||
function myBlockCompilerOpen(Fenom\Tokenizer $tokenizer, Fenom\Tag $scope)
|
||||
{
|
||||
$p = $scope->tpl->parseParams($tokenizer);
|
||||
return 'echo "PHP_VERSION: ".PHP_VERSION." (for ".' . $p["name"] . '.")";';
|
||||
}
|
||||
|
||||
function myBlockCompilerClose(Fenom\Tokenizer $tokenizer, Fenom\Scope $scope)
|
||||
function myBlockCompilerClose(Fenom\Tokenizer $tokenizer, Fenom\Tag $scope)
|
||||
{
|
||||
return 'echo "End of compiler";';
|
||||
}
|
||||
|
||||
function myBlockCompilerTag(Fenom\Tokenizer $tokenizer, Fenom\Scope $scope)
|
||||
function myBlockCompilerTag(Fenom\Tokenizer $tokenizer, Fenom\Tag $scope)
|
||||
{
|
||||
$p = $scope->tpl->parseParams($tokenizer);
|
||||
return 'echo "Tag ".' . $p["name"] . '." of compiler";';
|
||||
|
Loading…
Reference in New Issue
Block a user