Browse code

bug #2269 Bugfix: When rendering blocks of other templates, don't pass the local blocks array (derrabus, fabpot)

This PR was merged into the 1.x branch.

Discussion
----------

Bugfix: When rendering blocks of other templates, don't pass the local blocks array

This PR fixes symfony/symfony#20556.

When referring to a block of another template from within a template that also has a block with the same name, Twig renders the wrong block.

Commits
-------

8c090a7 added tests for block() when using a template argument
a5526f3 fixed block() is defined call when using a template argument
c04d077 Bugfix: When rendering blocks of other templates, don't pass the local blocks array.

Fabien Potencier authored on 19/11/2016 05:51:10
Showing 4 changed files
... ...
@@ -1,6 +1,6 @@
1 1
 * 1.28.1 (2016-XX-XX)
2 2
 
3
- * n/a
3
+ * fixed block() function when used with a template argument
4 4
 
5 5
 * 1.28.0 (2016-11-17)
6 6
 
... ...
@@ -39,46 +39,53 @@ class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
39 39
     public function compile(Twig_Compiler $compiler)
40 40
     {
41 41
         if ($this->getAttribute('is_defined_test')) {
42
-            $compiler
43
-                ->raw('$this->hasBlock(')
44
-                ->subcompile($this->getNode('name'))
45
-                ->raw(', $context, $blocks)')
46
-            ;
42
+            $this->compileTemplateCall($compiler, 'hasBlock');
47 43
         } else {
48 44
             if ($this->getAttribute('output')) {
49 45
                 $compiler->addDebugInfo($this);
50 46
 
51 47
                 $this
52
-                    ->compileTemplateCall($compiler)
53
-                    ->raw('->displayBlock(')
54
-                    ->subcompile($this->getNode('name'))
55
-                    ->raw(", \$context, \$blocks);\n")
56
-                ;
48
+                    ->compileTemplateCall($compiler, 'displayBlock')
49
+                    ->raw(";\n");
57 50
             } else {
58
-                $this
59
-                    ->compileTemplateCall($compiler)
60
-                    ->raw('->renderBlock(')
61
-                    ->subcompile($this->getNode('name'))
62
-                    ->raw(', $context, $blocks)')
63
-                ;
51
+                $this->compileTemplateCall($compiler, 'renderBlock');
64 52
             }
65 53
         }
66 54
     }
67 55
 
68
-    private function compileTemplateCall(Twig_Compiler $compiler)
56
+    private function compileTemplateCall(Twig_Compiler $compiler, $method)
57
+    {
58
+        if (!$this->hasNode('template')) {
59
+            $compiler->write('$this');
60
+        } else {
61
+            $compiler
62
+                ->write('$this->loadTemplate(')
63
+                ->subcompile($this->getNode('template'))
64
+                ->raw(', ')
65
+                ->repr($this->getTemplateName())
66
+                ->raw(', ')
67
+                ->repr($this->getTemplateLine())
68
+                ->raw(')')
69
+            ;
70
+        }
71
+
72
+        $compiler->raw(sprintf('->%s', $method));
73
+        $this->compileBlockArguments($compiler);
74
+
75
+        return $compiler;
76
+    }
77
+
78
+    private function compileBlockArguments(Twig_Compiler $compiler)
69 79
     {
80
+        $compiler
81
+            ->raw('(')
82
+            ->subcompile($this->getNode('name'))
83
+            ->raw(', $context');
84
+
70 85
         if (!$this->hasNode('template')) {
71
-            return $compiler->write('$this');
86
+            $compiler->raw(', $blocks');
72 87
         }
73 88
 
74
-        return $compiler
75
-            ->write('$this->loadTemplate(')
76
-            ->subcompile($this->getNode('template'))
77
-            ->raw(', ')
78
-            ->repr($this->getTemplateName())
79
-            ->raw(', ')
80
-            ->repr($this->getTemplateLine())
81
-            ->raw(')')
82
-        ;
89
+        return $compiler->raw(')');
83 90
     }
84 91
 }
85 92
new file mode 100644
... ...
@@ -0,0 +1,22 @@
1
+--TEST--
2
+"block" function with a template argument
3
+--TEMPLATE--
4
+{{ block('foo', 'included.twig') }}
5
+{{ block('foo', included_loaded) }}
6
+{{ block('foo', included_loaded_internal) }}
7
+{% set output = block('foo', 'included.twig') %}
8
+{{ output }}
9
+{% block foo %}NOT FOO{% endblock %}
10
+--TEMPLATE(included.twig)--
11
+{% block foo %}FOO{% endblock %}
12
+--DATA--
13
+return array(
14
+    'included_loaded' => $twig->load('included.twig'),
15
+    'included_loaded_internal' => $twig->loadTemplate('included.twig'),
16
+)
17
+--EXPECT--
18
+FOO
19
+FOO
20
+FOO
21
+FOO
22
+NOT FOO
0 23
new file mode 100644
... ...
@@ -0,0 +1,17 @@
1
+--TEST--
2
+"defined" support for blocks with a template argument
3
+--TEMPLATE--
4
+{{ block('foo', 'included.twig') is defined ? 'ok' : 'ko' }}
5
+{{ block('foo', included_loaded) is defined ? 'ok' : 'ko' }}
6
+{{ block('foo', included_loaded_internal) is defined ? 'ok' : 'ko' }}
7
+--TEMPLATE(included.twig)--
8
+{% block foo %}FOO{% endblock %}
9
+--DATA--
10
+return array(
11
+    'included_loaded' => $twig->load('included.twig'),
12
+    'included_loaded_internal' => $twig->loadTemplate('included.twig'),
13
+)
14
+--EXPECT--
15
+ok
16
+ok
17
+ok