Эх сурвалжийг харах

Put anchored dots behind {{%ANCHORED-DOT}} pragma.

Justin Hileman 10 жил өмнө
parent
commit
1b1757987a

+ 6 - 0
src/Mustache/Compiler.php

@@ -631,6 +631,12 @@ class Mustache_Compiler
             return 'last';
             return 'last';
         }
         }
 
 
+        if (isset($this->pragmas[Mustache_Engine::PRAGMA_ANCHORED_DOT]) && $this->pragmas[Mustache_Engine::PRAGMA_ANCHORED_DOT]) {
+            if (substr($id, 0, 1) === '.') {
+                return 'findAnchoredDot';
+            }
+        }
+
         if (strpos($id, '.') === false) {
         if (strpos($id, '.') === false) {
             return 'find';
             return 'find';
         }
         }

+ 35 - 4
src/Mustache/Context.php

@@ -128,13 +128,44 @@ class Mustache_Context
     {
     {
         $chunks = explode('.', $id);
         $chunks = explode('.', $id);
         $first  = array_shift($chunks);
         $first  = array_shift($chunks);
+        $value  = $this->findVariableInStack($first, $this->stack);
 
 
-        if ($first === '') {
-            $value = $this->last();
-        } else {
-            $value = $this->findVariableInStack($first, $this->stack);
+        foreach ($chunks as $chunk) {
+            if ($value === '') {
+                return $value;
+            }
+
+            $value = $this->findVariableInStack($chunk, array($value));
+        }
+
+        return $value;
+    }
+
+    /**
+     * Find an 'anchored dot notation' variable in the Context stack.
+     *
+     * This is the same as findDot(), except it looks in the top of the context
+     * stack for the first value, rather than searching the whole context stack
+     * and starting from there.
+     *
+     * @see Mustache_Context::findDot
+     *
+     * @throws Mustache_Exception_InvalidArgumentException if given an invalid anchored dot $id.
+     *
+     * @param string $id Dotted variable selector
+     *
+     * @return mixed Variable value, or '' if not found
+     */
+    public function findAnchoredDot($id)
+    {
+        $chunks = explode('.', $id);
+        $first  = array_shift($chunks);
+        if ($first !== '') {
+            throw new Mustache_Exception_InvalidArgumentException(sprintf('Unexpected id for findAnchoredDot: %s', $id));
         }
         }
 
 
+        $value  = $this->last();
+
         foreach ($chunks as $chunk) {
         foreach ($chunks as $chunk) {
             if ($value === '') {
             if ($value === '') {
                 return $value;
                 return $value;

+ 6 - 4
src/Mustache/Engine.php

@@ -26,13 +26,15 @@ class Mustache_Engine
     const VERSION        = '2.8.0';
     const VERSION        = '2.8.0';
     const SPEC_VERSION   = '1.1.2';
     const SPEC_VERSION   = '1.1.2';
 
 
-    const PRAGMA_FILTERS = 'FILTERS';
-    const PRAGMA_BLOCKS  = 'BLOCKS';
+    const PRAGMA_FILTERS      = 'FILTERS';
+    const PRAGMA_BLOCKS       = 'BLOCKS';
+    const PRAGMA_ANCHORED_DOT = 'ANCHORED-DOT';
 
 
     // Known pragmas
     // Known pragmas
     private static $knownPragmas = array(
     private static $knownPragmas = array(
-        self::PRAGMA_FILTERS => true,
-        self::PRAGMA_BLOCKS  => true,
+        self::PRAGMA_FILTERS      => true,
+        self::PRAGMA_BLOCKS       => true,
+        self::PRAGMA_ANCHORED_DOT => true,
     );
     );
 
 
     // Template cache
     // Template cache

+ 23 - 5
test/Mustache/Test/ContextTest.php

@@ -142,25 +142,43 @@ class Mustache_Test_ContextTest extends PHPUnit_Framework_TestCase
 
 
         $context->push($a);
         $context->push($a);
         $this->assertEquals('a', $context->find('name'));
         $this->assertEquals('a', $context->find('name'));
-        $this->assertEquals('a', $context->findDot('.name'));
+        $this->assertEquals('', $context->findDot('.name'));
+        $this->assertEquals('a', $context->findAnchoredDot('.name'));
         $this->assertEquals(1, $context->find('number'));
         $this->assertEquals(1, $context->find('number'));
-        $this->assertEquals(1, $context->findDot('.number'));
+        $this->assertEquals('', $context->findDot('.number'));
+        $this->assertEquals(1, $context->findAnchoredDot('.number'));
 
 
         $context->push($b);
         $context->push($b);
         $this->assertEquals('a', $context->find('name'));
         $this->assertEquals('a', $context->find('name'));
         $this->assertEquals(2, $context->find('number'));
         $this->assertEquals(2, $context->find('number'));
         $this->assertEquals('', $context->findDot('.name'));
         $this->assertEquals('', $context->findDot('.name'));
-        $this->assertEquals(2, $context->findDot('.number'));
+        $this->assertEquals('', $context->findDot('.number'));
+        $this->assertEquals('', $context->findAnchoredDot('.name'));
+        $this->assertEquals(2, $context->findAnchoredDot('.number'));
         $this->assertEquals('baby bee', $context->findDot('child.name'));
         $this->assertEquals('baby bee', $context->findDot('child.name'));
-        $this->assertEquals('baby bee', $context->findDot('.child.name'));
+        $this->assertEquals('', $context->findDot('.child.name'));
+        $this->assertEquals('baby bee', $context->findAnchoredDot('.child.name'));
 
 
         $context->push($c);
         $context->push($c);
         $this->assertEquals('cee', $context->find('name'));
         $this->assertEquals('cee', $context->find('name'));
-        $this->assertEquals('cee', $context->findDot('.name'));
+        $this->assertEquals('', $context->findDot('.name'));
+        $this->assertEquals('cee', $context->findAnchoredDot('.name'));
         $this->assertEquals(2, $context->find('number'));
         $this->assertEquals(2, $context->find('number'));
         $this->assertEquals('', $context->findDot('.number'));
         $this->assertEquals('', $context->findDot('.number'));
+        $this->assertEquals('', $context->findAnchoredDot('.number'));
         $this->assertEquals('baby bee', $context->findDot('child.name'));
         $this->assertEquals('baby bee', $context->findDot('child.name'));
         $this->assertEquals('', $context->findDot('.child.name'));
         $this->assertEquals('', $context->findDot('.child.name'));
+        $this->assertEquals('', $context->findAnchoredDot('.child.name'));
+    }
+
+    /**
+     * @expectedException Mustache_Exception_InvalidArgumentException
+     */
+    public function testAnchoredDotNotationThrowsExceptions()
+    {
+        $context = new Mustache_Context();
+        $context->push(array('a' => 1));
+        $context->findAnchoredDot('a');
     }
     }
 }
 }