This commit is contained in:
bzick 2013-08-05 13:07:16 +04:00
parent 09f952686b
commit c7a90789de
5 changed files with 62 additions and 40 deletions

View File

@ -3,8 +3,16 @@ CHANGELOG
## 1.2.0 ## 1.2.0
- Feature #28: macros may be called recursively
- Feature #29: add {unset} tag - Feature #29: add {unset} tag
- Add hook for loading modifiers and tags - Add hook for loading modifiers and tags
- Add hook for loading modifiers and tags
- Feature #3: Add string operator '~'
- Improve parsers: parserExp, parserVar, parserVariable, parserMacro
- Fix ternary bug
- Bugs--
- Tests++
- Docs++
## 1.1.0 ## 1.1.0

View File

@ -873,7 +873,7 @@ class Compiler
public static function macroOpen(Tokenizer $tokens, Scope $scope) public static function macroOpen(Tokenizer $tokens, Scope $scope)
{ {
$scope["name"] = $tokens->get(Tokenizer::MACRO_STRING); $scope["name"] = $tokens->get(Tokenizer::MACRO_STRING);
$scope["recursive"] = array(); $scope["recursive"] = false;
$args = array(); $args = array();
$defaults = array(); $defaults = array();
if (!$tokens->valid()) { if (!$tokens->valid()) {
@ -897,10 +897,11 @@ class Compiler
} }
$tokens->skipIf(')'); $tokens->skipIf(')');
$scope["macro"] = array( $scope["macro"] = array(
"id" => $scope->tpl->i++, "name" => $scope["name"],
"args" => $args, "args" => $args,
"defaults" => $defaults, "defaults" => $defaults,
"body" => "" "body" => "",
"recursive" => false
); );
return; return;
} }
@ -912,21 +913,9 @@ class Compiler
public static function macroClose(Tokenizer $tokens, Scope $scope) public static function macroClose(Tokenizer $tokens, Scope $scope)
{ {
if ($scope["recursive"]) { if ($scope["recursive"]) {
$switch = "switch(\$call['mark']) {\n"; $scope["macro"]["recursive"] = true;
foreach ($scope["recursive"] as $mark) {
$switch .= "case $mark: goto macro_$mark;\n";
}
$switch .= "}";
$stack = '$stack_' . $scope["macro"]['id'];
$scope["macro"]["body"] = '<?php ' . $stack . ' = array(); macro_' . $scope["macro"]['id'] . ': ?>' . $scope->cutContent() . '<?php if(' . $stack . ') {' . PHP_EOL .
'$call = array_pop(' . $stack . ');' . PHP_EOL .
'$tpl = $call["tpl"];' . PHP_EOL .
$switch . PHP_EOL .
'unset($call, ' . $stack . ');' . PHP_EOL .
'} ?>';
} else {
$scope["macro"]["body"] = $scope->cutContent();
} }
$scope["macro"]["body"] = $scope->cutContent();
$scope->tpl->macros[$scope["name"]] = $scope["macro"]; $scope->tpl->macros[$scope["name"]] = $scope["macro"];
} }

View File

@ -21,7 +21,8 @@ class Render extends \ArrayObject
"base_name" => "", "base_name" => "",
"scm" => false, "scm" => false,
"time" => 0, "time" => 0,
"depends" => array() "depends" => array(),
"macros" => array()
); );
/** /**
* @var \Closure * @var \Closure
@ -81,6 +82,7 @@ class Render extends \ArrayObject
$this->_scm = $props["scm"]; $this->_scm = $props["scm"];
$this->_time = $props["time"]; $this->_time = $props["time"];
$this->_depends = $props["depends"]; $this->_depends = $props["depends"];
$this->_macros = $props["macros"];
$this->_code = $code; $this->_code = $code;
} }
@ -183,6 +185,15 @@ class Render extends \ArrayObject
return true; return true;
} }
/**
* Get internal macro
* @param $name
* @return mixed
*/
public function getMacro($name) {
return $this->_macros[$name];
}
/** /**
* Execute template and write into output * Execute template and write into output
* @param array $values for template * @param array $values for template

View File

@ -397,18 +397,31 @@ class Template extends Render
*/ */
public function getTemplateCode() public function getTemplateCode()
{ {
if($this->macros) {
$macros = array();
foreach($this->macros as $m) {
if($m["recursive"]) {
$macros[] = "\t\t'".$m["name"]."' => function (\$tpl) {\n?>".$m["body"]."<?php\n}";
}
}
$macros = "\n".implode(",\n", $macros);
} else {
$macros = "";
}
$before = $this->_before ? $this->_before . "\n" : ""; $before = $this->_before ? $this->_before . "\n" : "";
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" .
$before . // some code 'before' template $before . // some code 'before' template
"return new Fenom\\Render(\$fenom, " . $this->_getClosureSource() . ", " . var_export(array( "return new Fenom\\Render(\$fenom, " . $this->_getClosureSource() . ", array(\n".
"options" => $this->_options, "\t'options' => {$this->_options},\n".
"provider" => $this->_scm, "\t'provider' => ".var_export($this->_scm, true).",\n".
"name" => $this->_name, "\t'name' => ".var_export($this->_name, true).",\n".
"base_name" => $this->_base_name, "\t'base_name' => ".var_export($this->_base_name, true).",\n".
"time" => $this->_time, "\t'time' => {$this->_time},\n".
"depends" => $this->_depends "\t'depends' => ".var_export($this->_base_name, true).",\n".
), true) . ");\n"; "\t'macros' => array({$macros}),
));\n";
} }
/** /**
@ -1323,14 +1336,14 @@ class Template extends Render
throw new InvalidUsageException("Macro '$name' require '$arg' argument"); throw new InvalidUsageException("Macro '$name' require '$arg' argument");
} }
} }
$args = $args ? '$tpl = ' . Compiler::toArray($args) . ';' : ''; $n = $this->i++;
if ($recursive) { if ($recursive) {
$n = $this->i++; $recursive['recursive'] = true;
$recursive['recursive'][] = $n; $body = '$tpl->getMacro("'.$name.'")->__invoke($tpl);';
return '$stack_' . $macro['id'] . '[] = array("tpl" => $tpl, "mark" => ' . $n . '); ' . $args . ' goto macro_' . $macro['id'] . '; macro_' . $n . ':';
} else { } else {
return '$_tpl = $tpl; ' . $args . ' ?>' . $macro["body"] . '<?php $tpl = $_tpl; unset($_tpl);'; $body = '?>'.$macro["body"].'<?php';
} }
return '$_tpl'.$n.' = $tpl->exchangeArray(' . Compiler::toArray($args) . ');' . PHP_EOL . $body . PHP_EOL . '$tpl->exchangeArray($_tpl'.$n.'); unset($_tpl'.$n.');';
} }
/** /**

View File

@ -54,17 +54,18 @@ class MacrosTest extends TestCase
{macro.factorial num=10}'); {macro.factorial num=10}');
} }
// public function _testSandbox() public function _testSandbox()
// { {
// try { try {
// $this->fenom->compile("macro_recursive.tpl"); $this->fenom->compile("macro_recursive.tpl");
// $this->fenom->flush(); // $this->fenom->flush();
// var_dump($this->fenom->fetch("macro_recursive.tpl", [])); // var_dump($this->fenom->fetch("macro_recursive.tpl", []));
// } catch (\Exception $e) { var_dump( $this->fenom->compile("macro_recursive.tpl")->getTemplateCode());
// var_dump($e->getMessage() . ": " . $e->getTraceAsString()); } catch (\Exception $e) {
// } var_dump($e->getMessage() . ": " . $e->getTraceAsString());
// exit; }
// } exit;
}
public function testMacros() public function testMacros()
{ {