Fix indents

This commit is contained in:
bzick 2013-07-03 12:10:50 +04:00
parent c76f5c8be0
commit 0457d5c379
5 changed files with 303 additions and 299 deletions

View File

@ -16,14 +16,14 @@ use Fenom\Template,
class Fenom { class Fenom {
const VERSION = '1.0'; const VERSION = '1.0';
/* Compiler types */ /* Compiler types */
const INLINE_COMPILER = 1; const INLINE_COMPILER = 1;
const BLOCK_COMPILER = 2; const BLOCK_COMPILER = 2;
const INLINE_FUNCTION = 3; const INLINE_FUNCTION = 3;
const BLOCK_FUNCTION = 4; const BLOCK_FUNCTION = 4;
const MODIFIER = 5; const MODIFIER = 5;
/* Options */ /* Options */
const DENY_METHODS = 0x10; const DENY_METHODS = 0x10;
const DENY_INLINE_FUNCS = 0x20; const DENY_INLINE_FUNCS = 0x20;
const FORCE_INCLUDE = 0x40; const FORCE_INCLUDE = 0x40;
@ -31,7 +31,7 @@ class Fenom {
const FORCE_COMPILE = 0xF0; const FORCE_COMPILE = 0xF0;
const DISABLE_CACHE = 0x1F0; const DISABLE_CACHE = 0x1F0;
/* Default parsers */ /* Default parsers */
const DEFAULT_CLOSE_COMPILER = 'Fenom\Compiler::stdClose'; const DEFAULT_CLOSE_COMPILER = 'Fenom\Compiler::stdClose';
const DEFAULT_FUNC_PARSER = 'Fenom\Compiler::stdFuncParser'; const DEFAULT_FUNC_PARSER = 'Fenom\Compiler::stdFuncParser';
const DEFAULT_FUNC_OPEN = 'Fenom\Compiler::stdFuncOpen'; const DEFAULT_FUNC_OPEN = 'Fenom\Compiler::stdFuncOpen';
@ -207,10 +207,10 @@ class Fenom {
'type' => self::INLINE_COMPILER, 'type' => self::INLINE_COMPILER,
'parser' => 'Fenom\Compiler::tagImport' 'parser' => 'Fenom\Compiler::tagImport'
), ),
'cycle' => array( 'cycle' => array(
'type' => self::INLINE_COMPILER, 'type' => self::INLINE_COMPILER,
'parser' => 'Fenom\Compiler::tagCycle' 'parser' => 'Fenom\Compiler::tagCycle'
) )
); );
/** /**
@ -231,7 +231,7 @@ class Fenom {
throw new InvalidArgumentException("Source must be a valid path or provider object"); throw new InvalidArgumentException("Source must be a valid path or provider object");
} }
$fenom = new static($provider); $fenom = new static($provider);
/* @var Fenom $fytro */ /* @var Fenom $fytro */
$fenom->setCompileDir($compile_dir); $fenom->setCompileDir($compile_dir);
if($options) { if($options) {
$fenom->setOptions($options); $fenom->setOptions($options);
@ -573,22 +573,22 @@ class Fenom {
return $this->getTemplate($template)->fetch($vars); return $this->getTemplate($template)->fetch($vars);
} }
/** /**
* *
* *
* @param string $template name of template * @param string $template name of template
* @param array $vars * @param array $vars
* @param $callback * @param $callback
* @param float $chunk * @param float $chunk
* @return \Fenom\Render * @return \Fenom\Render
* @example $fenom->pipe("products.yml.tpl", $iterators, [new SplFileObject("/tmp/products.yml"), "fwrite"], 512*1024) * @example $fenom->pipe("products.yml.tpl", $iterators, [new SplFileObject("/tmp/products.yml"), "fwrite"], 512*1024)
*/ */
public function pipe($template, array $vars, $callback, $chunk = 1e6) { public function pipe($template, array $vars, $callback, $chunk = 1e6) {
ob_start($callback, $chunk, true); ob_start($callback, $chunk, true);
$this->getTemplate($template)->display($vars); $this->getTemplate($template)->display($vars);
ob_end_flush(); ob_end_flush();
} }
/** /**
* Get template by name * Get template by name
@ -685,7 +685,7 @@ class Fenom {
* Flush internal memory template cache * Flush internal memory template cache
*/ */
public function flush() { public function flush() {
$this->_storage = array(); $this->_storage = array();
} }
/** /**

View File

@ -397,10 +397,10 @@ class Compiler {
$tpl->addDepend($tpl->_extends); $tpl->addDepend($tpl->_extends);
return ""; return "";
} else { // dynamic extends } else { // dynamic extends
if(!isset($tpl->_compatible)) { if(!isset($tpl->_compatible)) {
$tpl->_compatible = true; $tpl->_compatible = true;
} }
$tpl->_extends = $tpl_name; $tpl->_extends = $tpl_name;
return '$parent = $tpl->getStorage()->getTemplate('.$tpl_name.', \Fenom\Template::EXTENDED);'; return '$parent = $tpl->getStorage()->getTemplate('.$tpl_name.', \Fenom\Template::EXTENDED);';
} }
} }
@ -411,37 +411,37 @@ class Compiler {
* @param Template $tpl * @param Template $tpl
*/ */
public static function extendBody(&$body, $tpl) { public static function extendBody(&$body, $tpl) {
$t = $tpl; $t = $tpl;
if($tpl->uses) { if($tpl->uses) {
$tpl->blocks += $tpl->uses; $tpl->blocks += $tpl->uses;
} }
while(isset($t->_extends)) { while(isset($t->_extends)) {
$t = $t->_extends; $t = $t->_extends;
if(is_object($t)) { if(is_object($t)) {
/* @var \Fenom\Template $t */ /* @var \Fenom\Template $t */
$t->_extended = true; $t->_extended = true;
$tpl->addDepend($t); $tpl->addDepend($t);
$t->_compatible = &$tpl->_compatible; $t->_compatible = &$tpl->_compatible;
$t->blocks = &$tpl->blocks; $t->blocks = &$tpl->blocks;
$t->compile(); $t->compile();
if($t->uses) { if($t->uses) {
$tpl->blocks += $t->uses; $tpl->blocks += $t->uses;
} }
if(!isset($t->_extends)) { // last item => parent if(!isset($t->_extends)) { // last item => parent
if(empty($tpl->_compatible)) { if(empty($tpl->_compatible)) {
$body = $t->getBody(); $body = $t->getBody();
} else { } else {
$body = '<?php ob_start(); ?>'.$body.'<?php ob_end_clean(); ?>'.$t->getBody(); $body = '<?php ob_start(); ?>'.$body.'<?php ob_end_clean(); ?>'.$t->getBody();
} }
return; return;
} else { } else {
$body .= $t->getBody(); $body .= $t->getBody();
} }
} else { } else {
$body = '<?php ob_start(); ?>'.$body.'<?php ob_end_clean(); $parent->b = &$tpl->b; $parent->display((array)$tpl); unset($tpl->b, $parent->b); ?>'; $body = '<?php ob_start(); ?>'.$body.'<?php ob_end_clean(); $parent->b = &$tpl->b; $parent->display((array)$tpl); unset($tpl->b, $parent->b); ?>';
return; return;
} }
} }
} }
/** /**
@ -459,27 +459,27 @@ class Compiler {
if($name) { if($name) {
$donor = $tpl->getStorage()->getRawTemplate()->load($name, false); $donor = $tpl->getStorage()->getRawTemplate()->load($name, false);
$donor->_extended = true; $donor->_extended = true;
$donor->_extends = $tpl; $donor->_extends = $tpl;
$donor->_compatible = &$tpl->_compatible; $donor->_compatible = &$tpl->_compatible;
//$donor->blocks = &$tpl->blocks; //$donor->blocks = &$tpl->blocks;
$donor->compile(); $donor->compile();
$blocks = $donor->blocks; $blocks = $donor->blocks;
foreach($blocks as $name => $code) { foreach($blocks as $name => $code) {
if(isset($tpl->blocks[$name])) { if(isset($tpl->blocks[$name])) {
$tpl->blocks[$name] = $code; $tpl->blocks[$name] = $code;
unset($blocks[$name]); unset($blocks[$name]);
} }
} }
$tpl->uses = $blocks + $tpl->uses; $tpl->uses = $blocks + $tpl->uses;
$tpl->addDepend($donor); $tpl->addDepend($donor);
return '?>'.$donor->getBody().'<?php '; return '?>'.$donor->getBody().'<?php ';
} else { } else {
// throw new InvalidUsageException('template name must be given explicitly yet'); // throw new InvalidUsageException('template name must be given explicitly yet');
// under construction // under construction
$tpl->_compatible = true; $tpl->_compatible = true;
return '$donor = $tpl->getStorage()->getTemplate('.$cname.', \Fenom\Template::EXTENDED);'.PHP_EOL. return '$donor = $tpl->getStorage()->getTemplate('.$cname.', \Fenom\Template::EXTENDED);'.PHP_EOL.
'$donor->fetch((array)$tpl);'.PHP_EOL. '$donor->fetch((array)$tpl);'.PHP_EOL.
'$tpl->b += (array)$donor->b'; '$tpl->b += (array)$donor->b';
} }
} }
@ -495,8 +495,8 @@ class Compiler {
var_dump("".$scope->tpl); var_dump("".$scope->tpl);
$scope->tpl->_compatible = true; $scope->tpl->_compatible = true;
} }
$scope["cname"] = $scope->tpl->parsePlainArg($tokens, $name); $scope["cname"] = $scope->tpl->parsePlainArg($tokens, $name);
$scope["name"] = $name; $scope["name"] = $name;
} }
/** /**
@ -507,57 +507,57 @@ class Compiler {
*/ */
public static function tagBlockClose($tokens, Scope $scope) { public static function tagBlockClose($tokens, Scope $scope) {
$tpl = $scope->tpl; $tpl = $scope->tpl;
if(isset($tpl->_extends)) { // is child if(isset($tpl->_extends)) { // is child
if($scope["name"]) { // is scalar name if($scope["name"]) { // is scalar name
if($tpl->_compatible) { // is compatible mode if($tpl->_compatible) { // is compatible mode
$scope->replaceContent( $scope->replaceContent(
'<?php /* 1) Block '.$tpl.': '.$scope["cname"].' */'.PHP_EOL.' if(empty($tpl->b['.$scope["cname"].'])) { '. '<?php /* 1) Block '.$tpl.': '.$scope["cname"].' */'.PHP_EOL.' if(empty($tpl->b['.$scope["cname"].'])) { '.
'$tpl->b['.$scope["cname"].'] = function($tpl) { ?>'.PHP_EOL. '$tpl->b['.$scope["cname"].'] = function($tpl) { ?>'.PHP_EOL.
$scope->getContent(). $scope->getContent().
"<?php };". "<?php };".
"} ?>".PHP_EOL "} ?>".PHP_EOL
); );
} elseif(!isset($tpl->blocks[ $scope["name"] ])) { // is block not registered } elseif(!isset($tpl->blocks[ $scope["name"] ])) { // is block not registered
$tpl->blocks[ $scope["name"] ] = $scope->getContent(); $tpl->blocks[ $scope["name"] ] = $scope->getContent();
$scope->replaceContent( $scope->replaceContent(
'<?php /* 2) Block '.$tpl.': '.$scope["cname"].' '.$tpl->_compatible.' */'.PHP_EOL.' $tpl->b['.$scope["cname"].'] = function($tpl) { ?>'.PHP_EOL. '<?php /* 2) Block '.$tpl.': '.$scope["cname"].' '.$tpl->_compatible.' */'.PHP_EOL.' $tpl->b['.$scope["cname"].'] = function($tpl) { ?>'.PHP_EOL.
$scope->getContent(). $scope->getContent().
"<?php }; ?>".PHP_EOL "<?php }; ?>".PHP_EOL
); );
} }
} else { // dynamic name } else { // dynamic name
$tpl->_compatible = true; // enable compatible mode $tpl->_compatible = true; // enable compatible mode
$scope->replaceContent( $scope->replaceContent(
'<?php /* 3) Block '.$tpl.': '.$scope["cname"].' */'.PHP_EOL.' if(empty($tpl->b['.$scope["cname"].'])) { '. '<?php /* 3) Block '.$tpl.': '.$scope["cname"].' */'.PHP_EOL.' if(empty($tpl->b['.$scope["cname"].'])) { '.
'$tpl->b['.$scope["cname"].'] = function($tpl) { ?>'.PHP_EOL. '$tpl->b['.$scope["cname"].'] = function($tpl) { ?>'.PHP_EOL.
$scope->getContent(). $scope->getContent().
"<?php };". "<?php };".
"} ?>".PHP_EOL "} ?>".PHP_EOL
); );
} }
} else { // is parent } else { // is parent
if(isset($tpl->blocks[ $scope["name"] ])) { // has block if(isset($tpl->blocks[ $scope["name"] ])) { // has block
if($tpl->_compatible) { // compatible mode enabled if($tpl->_compatible) { // compatible mode enabled
$scope->replaceContent( $scope->replaceContent(
'<?php /* 4) Block '.$tpl.': '.$scope["cname"].' */'.PHP_EOL.' if(isset($tpl->b['.$scope["cname"].'])) { echo $tpl->b['.$scope["cname"].']->__invoke($tpl); } else {?>'.PHP_EOL. '<?php /* 4) Block '.$tpl.': '.$scope["cname"].' */'.PHP_EOL.' if(isset($tpl->b['.$scope["cname"].'])) { echo $tpl->b['.$scope["cname"].']->__invoke($tpl); } else {?>'.PHP_EOL.
$tpl->blocks[ $scope["name"] ]. $tpl->blocks[ $scope["name"] ].
'<?php } ?>'.PHP_EOL '<?php } ?>'.PHP_EOL
); );
} else { } else {
$scope->replaceContent($tpl->blocks[ $scope["name"] ]); $scope->replaceContent($tpl->blocks[ $scope["name"] ]);
} }
// } elseif(isset($tpl->_extended) || !empty($tpl->_compatible)) { // } elseif(isset($tpl->_extended) || !empty($tpl->_compatible)) {
} elseif(isset($tpl->_extended) && $tpl->_compatible || empty($tpl->_extended)) { } elseif(isset($tpl->_extended) && $tpl->_compatible || empty($tpl->_extended)) {
$scope->replaceContent( $scope->replaceContent(
'<?php /* 5) Block '.$tpl.': '.$scope["cname"].' */'.PHP_EOL.' if(isset($tpl->b['.$scope["cname"].'])) { echo $tpl->b['.$scope["cname"].']->__invoke($tpl); } else {?>'.PHP_EOL. '<?php /* 5) Block '.$tpl.': '.$scope["cname"].' */'.PHP_EOL.' if(isset($tpl->b['.$scope["cname"].'])) { echo $tpl->b['.$scope["cname"].']->__invoke($tpl); } else {?>'.PHP_EOL.
$scope->getContent(). $scope->getContent().
'<?php } ?>'.PHP_EOL '<?php } ?>'.PHP_EOL
); );
} }
} }
return ''; return '';
} }
@ -659,38 +659,38 @@ class Compiler {
return 'array('.implode(",", $_code).')'; return 'array('.implode(",", $_code).')';
} }
/** /**
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @param Scope $scope * @param Scope $scope
* @return string * @return string
*/ */
public static function varOpen(Tokenizer $tokens, Scope $scope) { public static function varOpen(Tokenizer $tokens, Scope $scope) {
$var = $scope->tpl->parseVariable($tokens, Template::DENY_MODS); $var = $scope->tpl->parseVariable($tokens, Template::DENY_MODS);
if($tokens->is('=')) { // inline tag {var ...} if($tokens->is('=')) { // inline tag {var ...}
$scope->is_closed = true; $scope->is_closed = true;
$tokens->next(); $tokens->next();
if($tokens->is("[")) { if($tokens->is("[")) {
return $var.'='.$scope->tpl->parseArray($tokens); return $var.'='.$scope->tpl->parseArray($tokens);
} else { } else {
return $var.'='.$scope->tpl->parseExp($tokens, true); return $var.'='.$scope->tpl->parseExp($tokens, true);
} }
} else { } else {
$scope["name"] = $var; $scope["name"] = $var;
if($tokens->is('|')) { if($tokens->is('|')) {
$scope["value"] = $scope->tpl->parseModifier($tokens, "ob_get_clean()"); $scope["value"] = $scope->tpl->parseModifier($tokens, "ob_get_clean()");
} else { } else {
$scope["value"] = "ob_get_clean()"; $scope["value"] = "ob_get_clean()";
} }
return 'ob_start();'; return 'ob_start();';
} }
} }
/** /**
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @param Scope $scope * @param Scope $scope
* @return string * @return string
*/ */
public static function varClose(Tokenizer $tokens, Scope $scope) { public static function varClose(Tokenizer $tokens, Scope $scope) {
return $scope["name"].'='.$scope["value"].';'; return $scope["name"].'='.$scope["value"].';';
} }
@ -723,11 +723,11 @@ class Compiler {
* @throws InvalidUsageException * @throws InvalidUsageException
*/ */
public static function tagCycle(Tokenizer $tokens, Template $tpl) { public static function tagCycle(Tokenizer $tokens, Template $tpl) {
if($tokens->is("[")) { if($tokens->is("[")) {
$exp = $tpl->parseArray($tokens); $exp = $tpl->parseArray($tokens);
} else { } else {
$exp = $tpl->parseExp($tokens, true); $exp = $tpl->parseExp($tokens, true);
} }
if($tokens->valid()) { if($tokens->valid()) {
$p = $tpl->parseParams($tokens); $p = $tpl->parseParams($tokens);
if(empty($p["index"])) { if(empty($p["index"])) {
@ -741,13 +741,13 @@ class Compiler {
} }
} }
/** /**
* Runtime cycle callback * Runtime cycle callback
* @param mixed $vals * @param mixed $vals
* @param $index * @param $index
* @return mixed * @return mixed
*/ */
public static function cycle($vals, $index) { public static function cycle($vals, $index) {
return $vals[$index % count($vals)]; return $vals[$index % count($vals)];
} }

View File

@ -26,9 +26,13 @@ class Provider implements ProviderInterface {
if(is_file($path)) { if(is_file($path)) {
unlink($path); unlink($path);
} elseif(is_dir($path)) { } elseif(is_dir($path)) {
$iterator = iterator_to_array(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, $iterator = iterator_to_array(
\FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS), new \RecursiveIteratorIterator(
\RecursiveIteratorIterator::CHILD_FIRST)); new \RecursiveDirectoryIterator($path,
\FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS),
\RecursiveIteratorIterator::CHILD_FIRST
)
);
foreach($iterator as $file) { foreach($iterator as $file) {
/* @var \splFileInfo $file*/ /* @var \splFileInfo $file*/
if($file->isFile()) { if($file->isFile()) {

View File

@ -18,21 +18,21 @@ use Fenom;
*/ */
class Template extends Render { class Template extends Render {
/** /**
* Disable array parser. * Disable array parser.
*/ */
const DENY_ARRAY = 1; const DENY_ARRAY = 1;
/** /**
* Disable modifier parser. * Disable modifier parser.
*/ */
const DENY_MODS = 2; const DENY_MODS = 2;
/** /**
* Template was extended * Template was extended
*/ */
const DYNAMIC_EXTEND = 0x1000; const DYNAMIC_EXTEND = 0x1000;
const EXTENDED = 0x2000; const EXTENDED = 0x2000;
const DYNAMIC_BLOCK = 0x4000; const DYNAMIC_BLOCK = 0x4000;
/** /**
* @var int shared counter * @var int shared counter
@ -54,13 +54,13 @@ class Template extends Render {
*/ */
public $blocks = array(); public $blocks = array();
public $uses = array(); public $uses = array();
public $parents = array(); public $parents = array();
public $_extends; public $_extends;
public $_extended = false; public $_extended = false;
public $_compatible; public $_compatible;
/** /**
* Call stack * Call stack
@ -126,9 +126,9 @@ class Template extends Render {
$this->_scm = $provider; $this->_scm = $provider;
$this->_base_name = substr($name, strlen($provider) + 1); $this->_base_name = substr($name, strlen($provider) + 1);
} else { } else {
$this->_base_name = $name; $this->_base_name = $name;
} }
$this->_provider = $this->_fenom->getProvider($provider); $this->_provider = $this->_fenom->getProvider($provider);
$this->_src = $this->_provider->getSource($this->_base_name, $this->_time); $this->_src = $this->_provider->getSource($this->_base_name, $this->_time);
if($compile) { if($compile) {
$this->compile(); $this->compile();
@ -158,59 +158,59 @@ class Template extends Render {
* @throws CompileException * @throws CompileException
*/ */
public function compile() { public function compile() {
$end = $pos = 0; $end = $pos = 0;
while(($start = strpos($this->_src, '{', $pos)) !== false) { // search open-symbol of tags while(($start = strpos($this->_src, '{', $pos)) !== false) { // search open-symbol of tags
switch($this->_src[$start + 1]) { // check next character switch($this->_src[$start + 1]) { // check next character
case "\n": case "\r": case "\t": case " ": case "}": // ignore the tag case "\n": case "\r": case "\t": case " ": case "}": // ignore the tag
$pos = $start + 1; $pos = $start + 1;
continue 2; continue 2;
case "*": // if comments case "*": // if comments
$end = strpos($this->_src, '*}', $start) + 1; // find end of the comment block $end = strpos($this->_src, '*}', $start) + 1; // find end of the comment block
if($end === false) { if($end === false) {
throw new CompileException("Unclosed comment block in line {$this->_line}", 0, 1, $this->_name, $this->_line); throw new CompileException("Unclosed comment block in line {$this->_line}", 0, 1, $this->_name, $this->_line);
} }
$this->_appendText(substr($this->_src, $pos, $start - $pos)); $this->_appendText(substr($this->_src, $pos, $start - $pos));
$comment = substr($this->_src, $start, $end - $start); // read the comment block for processing $comment = substr($this->_src, $start, $end - $start); // read the comment block for processing
$this->_line += substr_count($comment, "\n"); // count lines in comments $this->_line += substr_count($comment, "\n"); // count lines in comments
unset($comment); // cleanup unset($comment); // cleanup
$pos = $end + 1; $pos = $end + 1;
continue 2; continue 2;
} }
$frag = substr($this->_src, $pos, $start - $pos); // variable $frag contains chars after previous '}' and current '{' $frag = substr($this->_src, $pos, $start - $pos); // variable $frag contains chars after previous '}' and current '{'
$this->_appendText($frag); $this->_appendText($frag);
$from = $start; $from = $start;
reparse: { // yep, i use goto operator. For this algorithm it is good choice reparse: { // yep, i use goto operator. For this algorithm it is good choice
$end = strpos($this->_src, '}', $from); // search close-symbol of the tag $end = strpos($this->_src, '}', $from); // search close-symbol of the tag
if($end === false) { // if unexpected end of template if($end === false) { // if unexpected end of template
throw new CompileException("Unclosed tag in line {$this->_line}", 0, 1, $this->_name, $this->_line); throw new CompileException("Unclosed tag in line {$this->_line}", 0, 1, $this->_name, $this->_line);
} }
$tag = substr($this->_src, $start, $end - $start + 1); // variable $tag contains fenom tag '{...}' $tag = substr($this->_src, $start, $end - $start + 1); // variable $tag contains fenom tag '{...}'
$_tag = substr($tag, 1, -1); // strip delimiters '{' and '}' $_tag = substr($tag, 1, -1); // strip delimiters '{' and '}'
if($this->_ignore) { // check ignore if($this->_ignore) { // check ignore
if($_tag === '/ignore') { // turn off ignore if($_tag === '/ignore') { // turn off ignore
$this->_ignore = false; $this->_ignore = false;
} else { // still ignore } else { // still ignore
$this->_appendText($tag); $this->_appendText($tag);
} }
$pos = $start + strlen($tag); $pos = $start + strlen($tag);
continue; continue;
} else { } else {
$tokens = new Tokenizer($_tag); // tokenize the tag $tokens = new Tokenizer($_tag); // tokenize the tag
if($tokens->isIncomplete()) { // all strings finished? if($tokens->isIncomplete()) { // all strings finished?
$from = $end + 1; $from = $end + 1;
goto reparse; // need next close-symbol goto reparse; // need next close-symbol
} }
$this->_appendCode( $this->_tag($tokens) , $tag); // start the tag lexer $this->_appendCode( $this->_tag($tokens) , $tag); // start the tag lexer
$pos = $end + 1; // move search-pointer to end of the tag $pos = $end + 1; // move search-pointer to end of the tag
if($tokens->key()) { // if tokenizer have tokens - throws exceptions if($tokens->key()) { // if tokenizer have tokens - throws exceptions
throw new CompileException("Unexpected token '".$tokens->current()."' in {$this} line {$this->_line}, near '{".$tokens->getSnippetAsString(0,0)."' <- there", 0, E_ERROR, $this->_name, $this->_line); throw new CompileException("Unexpected token '".$tokens->current()."' in {$this} line {$this->_line}, near '{".$tokens->getSnippetAsString(0,0)."' <- there", 0, E_ERROR, $this->_name, $this->_line);
} }
} }
} }
unset($frag, $_tag, $tag); // cleanup unset($frag, $_tag, $tag); // cleanup
} }
gc_collect_cycles(); gc_collect_cycles();
@ -248,7 +248,7 @@ class Template extends Render {
* @param string $text * @param string $text
*/ */
private function _appendText($text) { private function _appendText($text) {
$this->_line += substr_count($text, "\n"); $this->_line += substr_count($text, "\n");
if($this->_filter) { if($this->_filter) {
if(strpos($text, "<?") === false) { if(strpos($text, "<?") === false) {
$this->_body .= $text; $this->_body .= $text;
@ -298,7 +298,7 @@ class Template extends Render {
if(!$code) { if(!$code) {
return; return;
} else { } else {
$this->_line += substr_count($source, "\n"); $this->_line += substr_count($source, "\n");
if(strpos($code, '?>') !== false) { if(strpos($code, '?>') !== false) {
$code = $this->_escapeCode($code); // paste PHP_EOL $code = $this->_escapeCode($code); // paste PHP_EOL
} }
@ -329,15 +329,15 @@ class Template extends Render {
*/ */
public function getTemplateCode() { public function getTemplateCode() {
return "<?php \n". return "<?php \n".
"/** Fenom template '".$this->_name."' compiled at ".date('Y-m-d H:i:s')." */\n". "/** Fenom template '".$this->_name."' compiled at ".date('Y-m-d H:i:s')." */\n".
"return new Fenom\\Render(\$fenom, ".$this->_getClosureSource().", ".var_export(array( "return new Fenom\\Render(\$fenom, ".$this->_getClosureSource().", ".var_export(array(
"options" => $this->_options, "options" => $this->_options,
"provider" => $this->_scm, "provider" => $this->_scm,
"name" => $this->_name, "name" => $this->_name,
"base_name" => $this->_base_name, "base_name" => $this->_base_name,
"time" => $this->_time, "time" => $this->_time,
"depends" => $this->_depends "depends" => $this->_depends
), true).");\n"; ), true).");\n";
} }
/** /**
@ -391,14 +391,14 @@ class Template extends Render {
return parent::fetch($values); return parent::fetch($values);
} }
/** /**
* Internal tags router * Internal tags router
* @param Tokenizer $tokens * @param Tokenizer $tokens
* *
* @throws SecurityException * @throws SecurityException
* @throws CompileException * @throws CompileException
* @return string executable PHP code * @return string executable PHP code
*/ */
private function _tag(Tokenizer $tokens) { private function _tag(Tokenizer $tokens) {
try { try {
if($tokens->is(Tokenizer::MACRO_STRING)) { if($tokens->is(Tokenizer::MACRO_STRING)) {
@ -776,13 +776,13 @@ class Template extends Render {
return $_scalar; return $_scalar;
} }
/** /**
* Parse string with or without variable * Parse string with or without variable
* *
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @throws UnexpectedTokenException * @throws UnexpectedTokenException
* @return string * @return string
*/ */
public function parseSubstr(Tokenizer $tokens) { public function parseSubstr(Tokenizer $tokens) {
if($tokens->is('"',"`")) { if($tokens->is('"',"`")) {
$stop = $tokens->current(); $stop = $tokens->current();

View File

@ -79,7 +79,7 @@ class Tokenizer {
public $tokens; public $tokens;
public $p = 0; public $p = 0;
public $quotes = 0; public $quotes = 0;
private $_max = 0; private $_max = 0;
private $_last_no = 0; private $_last_no = 0;
@ -143,55 +143,55 @@ class Tokenizer {
'true' => 1, 'false' => 1, 'null' => 1, 'TRUE' => 1, 'FALSE' => 1, 'NULL' => 1 'true' => 1, 'false' => 1, 'null' => 1, 'TRUE' => 1, 'FALSE' => 1, 'NULL' => 1
); );
/** /**
* @param $query * @param $query
*/ */
public function __construct($query) { public function __construct($query) {
$tokens = array(-1 => array(\T_WHITESPACE, '', '', 1)); $tokens = array(-1 => array(\T_WHITESPACE, '', '', 1));
$_tokens = token_get_all("<?php ".$query); $_tokens = token_get_all("<?php ".$query);
$line = 1; $line = 1;
array_shift($_tokens); array_shift($_tokens);
$i = 0; $i = 0;
foreach($_tokens as $token) { foreach($_tokens as $token) {
if(is_string($token)) { if(is_string($token)) {
if($token === '"' || $token === "'" || $token === "`") { if($token === '"' || $token === "'" || $token === "`") {
$this->quotes++; $this->quotes++;
} }
$tokens[] = array( $tokens[] = array(
$token, $token,
$token, $token,
"", "",
$line, $line,
); );
$i++; $i++;
} elseif ($token[0] === \T_WHITESPACE) { } elseif ($token[0] === \T_WHITESPACE) {
$tokens[$i-1][2] = $token[1]; $tokens[$i-1][2] = $token[1];
} else { } else {
$tokens[] = array( $tokens[] = array(
$token[0], $token[0],
$token[1], $token[1],
"", "",
$line = $token[2], $line = $token[2],
token_name($token[0]) // debug token_name($token[0]) // debug
); );
$i++; $i++;
} }
} }
unset($tokens[-1]); unset($tokens[-1]);
$this->tokens = $tokens; $this->tokens = $tokens;
$this->_max = count($this->tokens) - 1; $this->_max = count($this->tokens) - 1;
$this->_last_no = $this->tokens[$this->_max][3]; $this->_last_no = $this->tokens[$this->_max][3];
} }
/** /**
* Is incomplete mean some string not closed * Is incomplete mean some string not closed
* *
* @return int * @return int
*/ */
public function isIncomplete() { public function isIncomplete() {
return ($this->quotes % 2) || ($this->tokens[$this->_max][0] === T_ENCAPSED_AND_WHITESPACE); return ($this->quotes % 2) || ($this->tokens[$this->_max][0] === T_ENCAPSED_AND_WHITESPACE);
} }
/** /**
* Return the current element * Return the current element