Fixed recursively calling blocks in templates with inheritance
authorMartin Hasoň <martin.hason@gmail.com>
Thu, 13 Mar 2014 11:23:25 +0000 (12:23 +0100)
committerMartin Hasoň <martin.hason@gmail.com>
Thu, 13 Mar 2014 11:23:25 +0000 (12:23 +0100)
lib/Twig/Template.php
test/Twig/Tests/Fixtures/functions/recursive_block_with_inheritance.test [new file with mode: 0644]

index b13df5d..1fe203f 100644 (file)
@@ -105,9 +105,9 @@ abstract class Twig_Template implements Twig_TemplateInterface
         $name = (string) $name;
 
         if (isset($this->traits[$name])) {
-            $this->traits[$name][0]->displayBlock($name, $context, $blocks);
+            $this->traits[$name][0]->displayBlock($name, $context, $blocks, false);
         } elseif (false !== $parent = $this->getParent($context)) {
-            $parent->displayBlock($name, $context, $blocks);
+            $parent->displayBlock($name, $context, $blocks, false);
         } else {
             throw new Twig_Error_Runtime(sprintf('The template has no parent and no traits defining the "%s" block', $name), -1, $this->getTemplateName());
         }
@@ -119,18 +119,18 @@ abstract class Twig_Template implements Twig_TemplateInterface
      * This method is for internal use only and should never be called
      * directly.
      *
-     * @param string $name    The block name to display
-     * @param array  $context The context
-     * @param array  $blocks  The current set of blocks
+     * @param string  $name      The block name to display
+     * @param array   $context   The context
+     * @param array   $blocks    The current set of blocks
+     * @param Boolean $useBlocks Whether to use the current set of blocks
      */
-    public function displayBlock($name, array $context, array $blocks = array())
+    public function displayBlock($name, array $context, array $blocks = array(), $useBlocks = true)
     {
         $name = (string) $name;
 
-        if (isset($blocks[$name])) {
+        if ($useBlocks && isset($blocks[$name])) {
             $template = $blocks[$name][0];
             $block = $blocks[$name][1];
-            unset($blocks[$name]);
         } elseif (isset($this->blocks[$name])) {
             $template = $this->blocks[$name][0];
             $block = $this->blocks[$name][1];
@@ -148,7 +148,7 @@ abstract class Twig_Template implements Twig_TemplateInterface
                 throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $template->getTemplateName(), $e);
             }
         } elseif (false !== $parent = $this->getParent($context)) {
-            $parent->displayBlock($name, $context, array_merge($this->blocks, $blocks));
+            $parent->displayBlock($name, $context, array_merge($this->blocks, $blocks), false);
         }
     }
 
@@ -178,16 +178,17 @@ abstract class Twig_Template implements Twig_TemplateInterface
      * This method is for internal use only and should never be called
      * directly.
      *
-     * @param string $name    The block name to render
-     * @param array  $context The context
-     * @param array  $blocks  The current set of blocks
+     * @param string  $name      The block name to render
+     * @param array   $context   The context
+     * @param array   $blocks    The current set of blocks
+     * @param Boolean $useBlocks Whether to use the current set of blocks
      *
      * @return string The rendered block
      */
-    public function renderBlock($name, array $context, array $blocks = array())
+    public function renderBlock($name, array $context, array $blocks = array(), $useBlocks = true)
     {
         ob_start();
-        $this->displayBlock($name, $context, $blocks);
+        $this->displayBlock($name, $context, $blocks, $useBlocks);
 
         return ob_get_clean();
     }
diff --git a/test/Twig/Tests/Fixtures/functions/recursive_block_with_inheritance.test b/test/Twig/Tests/Fixtures/functions/recursive_block_with_inheritance.test
new file mode 100644 (file)
index 0000000..f39712d
--- /dev/null
@@ -0,0 +1,21 @@
+--TEST--
+"block" function recursively called in a parent template
+--TEMPLATE--
+{% extends "ordered_menu.twig" %}
+{% block label %}"{{ parent() }}"{% endblock %}
+{% block list %}{% set class = 'b' %}{{ parent() }}{% endblock %}
+--TEMPLATE(ordered_menu.twig)--
+{% extends "menu.twig" %}
+{% block list %}{% set class = class|default('a') %}<ol class="{{ class }}">{{ block('children') }}</ol>{% endblock %}
+--TEMPLATE(menu.twig)--
+{% extends "base.twig" %}
+{% block list %}<ul>{{ block('children') }}</ul>{% endblock %}
+{% block children %}{% set currentItem = item %}{% for item in currentItem %}{{ block('item') }}{% endfor %}{% set item = currentItem %}{% endblock %}
+{% block item %}<li>{% if item is not iterable %}{{ block('label') }}{% else %}{{ block('list') }}{% endif %}</li>{% endblock %}
+{% block label %}{{ item }}{{ block('unknown') }}{% endblock %}
+--TEMPLATE(base.twig)--
+{{ block('list') }}
+--DATA--
+return array('item' => array('1', '2', array('3.1', array('3.2.1', '3.2.2'), '3.4')))
+--EXPECT--
+<ol class="b"><li>"1"</li><li>"2"</li><li><ol class="b"><li>"3.1"</li><li><ol class="b"><li>"3.2.1"</li><li>"3.2.2"</li></ol></li><li>"3.4"</li></ol></li></ol>