From c7a90789de42f841b7e79d40342d6698176d61e2 Mon Sep 17 00:00:00 2001 From: bzick Date: Mon, 5 Aug 2013 13:07:16 +0400 Subject: [PATCH] Done #28 --- CHANGELOG.md | 8 +++++++ src/Fenom/Compiler.php | 23 +++++-------------- src/Fenom/Render.php | 13 ++++++++++- src/Fenom/Template.php | 39 +++++++++++++++++++++----------- tests/cases/Fenom/MacrosTest.php | 19 ++++++++-------- 5 files changed, 62 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ad40e2..35a2e85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,16 @@ CHANGELOG ## 1.2.0 +- Feature #28: macros may be called recursively - Feature #29: add {unset} tag - 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 diff --git a/src/Fenom/Compiler.php b/src/Fenom/Compiler.php index 1ebb623..904e5ee 100644 --- a/src/Fenom/Compiler.php +++ b/src/Fenom/Compiler.php @@ -873,7 +873,7 @@ class Compiler public static function macroOpen(Tokenizer $tokens, Scope $scope) { $scope["name"] = $tokens->get(Tokenizer::MACRO_STRING); - $scope["recursive"] = array(); + $scope["recursive"] = false; $args = array(); $defaults = array(); if (!$tokens->valid()) { @@ -897,10 +897,11 @@ class Compiler } $tokens->skipIf(')'); $scope["macro"] = array( - "id" => $scope->tpl->i++, + "name" => $scope["name"], "args" => $args, "defaults" => $defaults, - "body" => "" + "body" => "", + "recursive" => false ); return; } @@ -912,21 +913,9 @@ class Compiler public static function macroClose(Tokenizer $tokens, Scope $scope) { if ($scope["recursive"]) { - $switch = "switch(\$call['mark']) {\n"; - foreach ($scope["recursive"] as $mark) { - $switch .= "case $mark: goto macro_$mark;\n"; - } - $switch .= "}"; - $stack = '$stack_' . $scope["macro"]['id']; - $scope["macro"]["body"] = '' . $scope->cutContent() . ''; - } else { - $scope["macro"]["body"] = $scope->cutContent(); + $scope["macro"]["recursive"] = true; } + $scope["macro"]["body"] = $scope->cutContent(); $scope->tpl->macros[$scope["name"]] = $scope["macro"]; } diff --git a/src/Fenom/Render.php b/src/Fenom/Render.php index 15a8b1d..f01bd53 100644 --- a/src/Fenom/Render.php +++ b/src/Fenom/Render.php @@ -21,7 +21,8 @@ class Render extends \ArrayObject "base_name" => "", "scm" => false, "time" => 0, - "depends" => array() + "depends" => array(), + "macros" => array() ); /** * @var \Closure @@ -81,6 +82,7 @@ class Render extends \ArrayObject $this->_scm = $props["scm"]; $this->_time = $props["time"]; $this->_depends = $props["depends"]; + $this->_macros = $props["macros"]; $this->_code = $code; } @@ -183,6 +185,15 @@ class Render extends \ArrayObject return true; } + /** + * Get internal macro + * @param $name + * @return mixed + */ + public function getMacro($name) { + return $this->_macros[$name]; + } + /** * Execute template and write into output * @param array $values for template diff --git a/src/Fenom/Template.php b/src/Fenom/Template.php index 8d6c16e..0f22787 100644 --- a/src/Fenom/Template.php +++ b/src/Fenom/Template.php @@ -397,18 +397,31 @@ class Template extends Render */ 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"]."_before ? $this->_before . "\n" : ""; return "_name . "' compiled at " . date('Y-m-d H:i:s') . " */\n" . $before . // some code 'before' template - "return new Fenom\\Render(\$fenom, " . $this->_getClosureSource() . ", " . var_export(array( - "options" => $this->_options, - "provider" => $this->_scm, - "name" => $this->_name, - "base_name" => $this->_base_name, - "time" => $this->_time, - "depends" => $this->_depends - ), true) . ");\n"; + "return new Fenom\\Render(\$fenom, " . $this->_getClosureSource() . ", array(\n". + "\t'options' => {$this->_options},\n". + "\t'provider' => ".var_export($this->_scm, true).",\n". + "\t'name' => ".var_export($this->_name, true).",\n". + "\t'base_name' => ".var_export($this->_base_name, true).",\n". + "\t'time' => {$this->_time},\n". + "\t'depends' => ".var_export($this->_base_name, true).",\n". + "\t'macros' => array({$macros}), + ));\n"; } /** @@ -1323,14 +1336,14 @@ class Template extends Render throw new InvalidUsageException("Macro '$name' require '$arg' argument"); } } - $args = $args ? '$tpl = ' . Compiler::toArray($args) . ';' : ''; + $n = $this->i++; if ($recursive) { - $n = $this->i++; - $recursive['recursive'][] = $n; - return '$stack_' . $macro['id'] . '[] = array("tpl" => $tpl, "mark" => ' . $n . '); ' . $args . ' goto macro_' . $macro['id'] . '; macro_' . $n . ':'; + $recursive['recursive'] = true; + $body = '$tpl->getMacro("'.$name.'")->__invoke($tpl);'; } else { - return '$_tpl = $tpl; ' . $args . ' ?>' . $macro["body"] . ''.$macro["body"].'exchangeArray(' . Compiler::toArray($args) . ');' . PHP_EOL . $body . PHP_EOL . '$tpl->exchangeArray($_tpl'.$n.'); unset($_tpl'.$n.');'; } /** diff --git a/tests/cases/Fenom/MacrosTest.php b/tests/cases/Fenom/MacrosTest.php index ded112f..7b5c32c 100644 --- a/tests/cases/Fenom/MacrosTest.php +++ b/tests/cases/Fenom/MacrosTest.php @@ -54,17 +54,18 @@ class MacrosTest extends TestCase {macro.factorial num=10}'); } -// public function _testSandbox() -// { -// try { -// $this->fenom->compile("macro_recursive.tpl"); + public function _testSandbox() + { + try { + $this->fenom->compile("macro_recursive.tpl"); // $this->fenom->flush(); // var_dump($this->fenom->fetch("macro_recursive.tpl", [])); -// } catch (\Exception $e) { -// var_dump($e->getMessage() . ": " . $e->getTraceAsString()); -// } -// exit; -// } + var_dump( $this->fenom->compile("macro_recursive.tpl")->getTemplateCode()); + } catch (\Exception $e) { + var_dump($e->getMessage() . ": " . $e->getTraceAsString()); + } + exit; + } public function testMacros() {