ソースを参照

Separate stacks are necessary for blocks to be resolved independently of variables. Renamed parent_* to block_*.

Dan Miller 11 年 前
コミット
af8a62c5e2

+ 17 - 18
src/Mustache/Compiler.php

@@ -110,8 +110,8 @@ class Mustache_Compiler
                     );
                     break;
 
-                case Mustache_Tokenizer::T_PARENT_ARG:
-                    $code .= $this->parentArg(
+                case Mustache_Tokenizer::T_BLOCK_ARG:
+                    $code .= $this->blockArg(
                         $node[Mustache_Tokenizer::NODES],
                         $node[Mustache_Tokenizer::NAME],
                         $node[Mustache_Tokenizer::INDEX],
@@ -122,8 +122,8 @@ class Mustache_Compiler
                     );
                     break;
 
-                case Mustache_Tokenizer::T_PARENT_VAR:
-                    $code .= $this->parentVar(
+                case Mustache_Tokenizer::T_BLOCK_VAR:
+                    $code .= $this->blockVar(
                         $node[Mustache_Tokenizer::NODES],
                         $node[Mustache_Tokenizer::NAME],
                         $node[Mustache_Tokenizer::INDEX],
@@ -154,7 +154,6 @@ class Mustache_Compiler
                     throw new Mustache_Exception_SyntaxException(sprintf('Unknown token type: %s', $node[Mustache_Tokenizer::TYPE]), $node);
             }
         }
-
         return $code;
     }
 
@@ -211,7 +210,7 @@ class Mustache_Compiler
         return sprintf($this->prepare($klass, 0, false, true), $name, $callable, $code, $sections);
     }
 
-    const PARENT_VAR = '
+    const BLOCK_VAR = '
         $value = $this->resolveValue($context->%s(%s), $context, $indent);
         if($value && !is_array($value) && !is_object($value)) {
             $buffer .= %s;
@@ -220,22 +219,22 @@ class Mustache_Compiler
         }
     ';
 
-    private function parentVar($nodes, $id, $start, $end, $otag, $ctag, $level)
+    private function blockVar($nodes, $id, $start, $end, $otag, $ctag, $level)
     {
-        $method = 'findFromParent';
+        $method = 'findInBlock';
         $id_str = var_export($id, true);
         $value  = $this->getEscape();
 
-        return sprintf($this->prepare(self::PARENT_VAR, $level), $method, $id_str, $value, $this->walk($nodes, 2));
+        return sprintf($this->prepare(self::BLOCK_VAR, $level), $method, $id_str, $value, $this->walk($nodes, 2));
     }
 
-    const PARENT_ARG = '
-        // %s parent_arg
+    const BLOCK_ARG = '
+        // %s block_arg
         $value = $this->section%s($context, $indent, true);
         $newContext[%s] = %s$value;
     ';
 
-    private function parentArg($nodes, $id, $start, $end, $otag, $ctag, $level)
+    private function blockArg($nodes, $id, $start, $end, $otag, $ctag, $level)
     {
         $key = $this->section($nodes, $id, $start, $end, $otag, $ctag, $level, true);
         $filters = '';
@@ -247,7 +246,7 @@ class Mustache_Compiler
         $method   = $this->getFindMethod($id);
         $id       = var_export($id, true);
 
-        return sprintf($this->prepare(self::PARENT_ARG, $level), $key, $key, $id, $this->flushIndent());
+        return sprintf($this->prepare(self::BLOCK_ARG, $level), $key, $key, $id, $this->flushIndent());
     }
 
     const SECTION_CALL = '
@@ -384,9 +383,9 @@ class Mustache_Compiler
     const PARENT = '
 
         if ($parent = $this->mustache->LoadPartial(%s)) {
-            $context->push($newContext);
+            $context->pushBlockContext($newContext);
             $buffer .= $parent->renderInternal($context, $indent);
-            $context->pop();
+            $context->popBlockContext();
         }
     ';
 
@@ -394,7 +393,7 @@ class Mustache_Compiler
     {
         $block = '';
 
-        $real_children = array_filter($children, array(__CLASS__, 'return_only_parent_args'));
+        $real_children = array_filter($children, array(__CLASS__, 'return_only_block_args'));
 
         $block = $this->walk($real_children, $level);
 
@@ -405,9 +404,9 @@ class Mustache_Compiler
         );
     }
 
-    private static function return_only_parent_args($child)
+    private static function return_only_block_args($child)
     {
-        return $child[Mustache_Tokenizer::TYPE] == Mustache_Tokenizer::T_PARENT_ARG;
+        return $child[Mustache_Tokenizer::TYPE] == Mustache_Tokenizer::T_BLOCK_ARG;
     }
 
     const VARIABLE = '

+ 13 - 2
src/Mustache/Context.php

@@ -15,6 +15,7 @@
 class Mustache_Context
 {
     private $stack = array();
+    private $block_stack = array();
 
     /**
      * Mustache rendering Context constructor.
@@ -38,6 +39,11 @@ class Mustache_Context
         array_push($this->stack, $value);
     }
 
+    public function pushBlockContext($value)
+    {
+        array_push($this->block_stack, $value);
+    }
+
     /**
      * Pop the last Context frame from the stack.
      *
@@ -48,6 +54,11 @@ class Mustache_Context
         return array_pop($this->stack);
     }
 
+    public function popBlockContext()
+    {
+        return array_pop($this->block_stack);
+    }
+
     /**
      * Get the last Context frame.
      *
@@ -120,9 +131,9 @@ class Mustache_Context
         return $value;
     }
 
-    public function findFromParent($id)
+    public function findInBlock($id)
     {
-        foreach($this->stack as $context) {
+        foreach($this->block_stack as $context) {
             if (is_array($context) && array_key_exists($id, $context)) {
                 return $context[$id];
             }

+ 2 - 2
src/Mustache/Parser.php

@@ -108,9 +108,9 @@ class Mustache_Parser
                     $nodes[] = $this->buildTree($tokens, $token);
                     break;
 
-                case Mustache_Tokenizer::T_PARENT_VAR:
+                case Mustache_Tokenizer::T_BLOCK_VAR:
                     if ($parent[Mustache_Tokenizer::TYPE] == Mustache_Tokenizer::T_PARENT) {
-                        $token[Mustache_Tokenizer::TYPE] = Mustache_Tokenizer::T_PARENT_ARG;
+                        $token[Mustache_Tokenizer::TYPE] = Mustache_Tokenizer::T_BLOCK_ARG;
                     }
                     $this->clearStandaloneLines($nodes, $tokens);
                     $nodes[] = $this->buildTree($tokens, $token);

+ 4 - 1
src/Mustache/Template.php

@@ -61,10 +61,13 @@ abstract class Mustache_Template
      * @param mixed $context Array or object rendering context (default: array())
      *
      * @return string Rendered template
+     * TODO construct a parent context stack here and pass it in
      */
     public function render($context = array())
     {
-        return $this->renderInternal($this->prepareContextStack($context));
+        return $this->renderInternal(
+            $this->prepareContextStack($context)
+        );
     }
 
     /**

+ 3 - 3
src/Mustache/Tokenizer.php

@@ -35,8 +35,8 @@ class Mustache_Tokenizer
     const T_UNESCAPED_2  = '&';
     const T_TEXT         = '_t';
     const T_PRAGMA       = '%';
-    const T_PARENT_VAR   = '$';
-    const T_PARENT_ARG   = '$arg';
+    const T_BLOCK_VAR   = '$';
+    const T_BLOCK_ARG   = '$arg';
 
     // Valid token types
     private static $tagTypes = array(
@@ -51,7 +51,7 @@ class Mustache_Tokenizer
         self::T_UNESCAPED    => true,
         self::T_UNESCAPED_2  => true,
         self::T_PRAGMA       => true,
-        self::T_PARENT_VAR   => true,
+        self::T_BLOCK_VAR   => true,
     );
 
     // Interpolated tags

+ 38 - 0
test/Mustache/Test/Functional/InheritanceTest.php

@@ -137,6 +137,44 @@ class Mustache_Test_Functional_InheritanceTest extends PHPUnit_Framework_TestCas
         $this->assertEquals('test |override1 default| |override2 default|', $tpl->render($data));
     }
 
+    public function testDataDoesNotOverrideBlock()
+    {
+        $partials = array(
+            'include' => '{{$var}}var in include{{/var}}'
+        );
+
+        $this->mustache->setPartials($partials);
+
+        $tpl = $this->mustache->loadTemplate(
+            '{{<include}}{{$var}}var in template{{/var}}{{/include}}'
+        );
+
+        $data = array(
+            'var' => 'var in data'
+        );
+
+        $this->assertEquals('var in template', $tpl->render($data));
+    }
+
+    public function testDataDoesNotOverrideDefaultBlockValue()
+    {
+        $partials = array(
+            'include' => '{{$var}}var in include{{/var}}'
+        );
+
+        $this->mustache->setPartials($partials);
+
+        $tpl = $this->mustache->loadTemplate(
+            '{{<include}}{{/include}}'
+        );
+
+        $data = array(
+            'var' => 'var in data'
+        );
+
+        $this->assertEquals('var in include', $tpl->render($data));
+    }
+
     public function testOverridePartialWithNewlines()
     {
          $partials = array(

+ 4 - 4
test/Mustache/Test/ParserTest.php

@@ -128,7 +128,7 @@ class Mustache_Test_ParserTest extends PHPUnit_Framework_TestCase
                         Mustache_Tokenizer::INDEX => 8
                     ),
                     array(
-                        Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_PARENT_VAR,
+                        Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_BLOCK_VAR,
                         Mustache_Tokenizer::NAME => 'bar',
                         Mustache_Tokenizer::OTAG => '{{',
                         Mustache_Tokenizer::CTAG => '}}',
@@ -168,7 +168,7 @@ class Mustache_Test_ParserTest extends PHPUnit_Framework_TestCase
                         Mustache_Tokenizer::END => 27,
                         Mustache_Tokenizer::NODES => array(
                             array(
-                                Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_PARENT_ARG,
+                                Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_BLOCK_ARG,
                                 Mustache_Tokenizer::NAME => 'bar',
                                 Mustache_Tokenizer::OTAG => '{{',
                                 Mustache_Tokenizer::CTAG => '}}',
@@ -191,7 +191,7 @@ class Mustache_Test_ParserTest extends PHPUnit_Framework_TestCase
             array(
                 array(
                     array(
-                        Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_PARENT_VAR,
+                        Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_BLOCK_VAR,
                         Mustache_Tokenizer::NAME => 'foo',
                         Mustache_Tokenizer::OTAG => '{{',
                         Mustache_Tokenizer::CTAG => '}}',
@@ -213,7 +213,7 @@ class Mustache_Test_ParserTest extends PHPUnit_Framework_TestCase
                 ),
                 array(
                     array(
-                        Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_PARENT_VAR,
+                        Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_BLOCK_VAR,
                         Mustache_Tokenizer::NAME => 'foo',
                         Mustache_Tokenizer::OTAG => '{{',
                         Mustache_Tokenizer::CTAG => '}}',

+ 1 - 1
test/Mustache/Test/TokenizerTest.php

@@ -195,7 +195,7 @@ class Mustache_Test_TokenizerTest extends PHPUnit_Framework_TestCase
                 null,
                 array(
                     array(
-                        Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_PARENT_VAR,
+                        Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_BLOCK_VAR,
                         Mustache_Tokenizer::NAME => 'arg',
                         Mustache_Tokenizer::OTAG => '{{',
                         Mustache_Tokenizer::CTAG => '}}',