diff --git a/lib/Twig/Template.php b/lib/Twig/Template.php index 54f6b0dcd..bedc7e9ca 100644 --- a/lib/Twig/Template.php +++ b/lib/Twig/Template.php @@ -197,12 +197,16 @@ abstract class Twig_Template implements Twig_TemplateInterface $block = null; } - if (null !== $template) { - // avoid RCEs when sandbox is enabled - if (!$template instanceof self) { - throw new LogicException('A block must be a method on a Twig_Template instance.'); - } + // avoid RCEs when sandbox is enabled + if (null !== $template && !$template instanceof self) { + throw new LogicException('A block must be a method on a Twig_Template instance.'); + } + if (!$this->hasBlock($name, $context, $blocks)) { + @trigger_error(sprintf('Displaying undefined block "%s" in template "%s" is deprecated since version 1.29 and will throw an exception in 2.0.', $name, $this->getTemplateName()), E_USER_DEPRECATED); + } + + if (null !== $template) { try { $template->$block($context, $blocks); } catch (Twig_Error $e) { diff --git a/test/Twig/Tests/Fixtures/functions/recursive_block_with_inheritance.test b/test/Twig/Tests/Fixtures/functions/recursive_block_with_inheritance.test index f39712da8..bf0556d24 100644 --- a/test/Twig/Tests/Fixtures/functions/recursive_block_with_inheritance.test +++ b/test/Twig/Tests/Fixtures/functions/recursive_block_with_inheritance.test @@ -12,7 +12,7 @@ {% block list %}{% endblock %} {% block children %}{% set currentItem = item %}{% for item in currentItem %}{{ block('item') }}{% endfor %}{% set item = currentItem %}{% endblock %} {% block item %}
  • {% if item is not iterable %}{{ block('label') }}{% else %}{{ block('list') }}{% endif %}
  • {% endblock %} -{% block label %}{{ item }}{{ block('unknown') }}{% endblock %} +{% block label %}{{ item }}{% endblock %} --TEMPLATE(base.twig)-- {{ block('list') }} --DATA-- diff --git a/test/Twig/Tests/LegacyFixtures/functions/undefined_block.legacy.test b/test/Twig/Tests/LegacyFixtures/functions/undefined_block.legacy.test new file mode 100644 index 000000000..62e24f0f4 --- /dev/null +++ b/test/Twig/Tests/LegacyFixtures/functions/undefined_block.legacy.test @@ -0,0 +1,12 @@ +--TEST-- +"block" function with undefined block +--TEMPLATE-- +{% extends "base.twig" %} +{% block foo %}{{ parent() }}{{ block('unknown') }}{{ block('bar') }}{% endblock %} +--TEMPLATE(base.twig)-- +{% block foo %}Foo{% endblock %} +{% block bar %}Bar{% endblock %} +--DATA-- +return array() +--EXPECT-- +FooBarBar diff --git a/test/Twig/Tests/TemplateTest.php b/test/Twig/Tests/TemplateTest.php index 610b8c6c1..821e2c7a8 100644 --- a/test/Twig/Tests/TemplateTest.php +++ b/test/Twig/Tests/TemplateTest.php @@ -214,15 +214,17 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase $this->assertNotInstanceof('Twig_Markup', $template->getAttribute($template1, 'empty')); $this->assertSame('', $template->getAttribute($template1, 'empty')); + $blocks = array('name' => array($template1, 'block_name')); + // trigger some deprecation notice messages to check them with @expectedDeprecation - $template->getAttribute($template, 'renderBlock', array('name', array())); - $template->getAttribute($template, 'displayBlock', array('name', array())); + $template->getAttribute($template, 'renderBlock', array('name', array(), $blocks)); + $template->getAttribute($template, 'displayBlock', array('name', array(), $blocks)); $template->getAttribute($template, 'hasBlock', array('name', array())); $template->getAttribute($template, 'render', array(array())); $template->getAttribute($template, 'display', array(array())); - $template->getAttribute($template1, 'renderBlock', array('name', array())); - $template->getAttribute($template1, 'displayBlock', array('name', array())); + $template->getAttribute($template1, 'renderBlock', array('name', array(), $blocks)); + $template->getAttribute($template1, 'displayBlock', array('name', array(), $blocks)); $template->getAttribute($template1, 'hasBlock', array('name', array())); $template->getAttribute($template1, 'render', array(array())); $template->getAttribute($template1, 'display', array(array())); @@ -233,6 +235,20 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase $this->assertFalse($template->getAttribute($template1, 'displayWithErrorHandling', array(), Twig_Template::METHOD_CALL, true)); } + /** + * @group legacy + * @expectedDeprecation Displaying undefined block "unknown" in template "index.twig" is deprecated since version 1.29 and will throw an exception in 2.0. + * @expectedDeprecation Displaying undefined block "unknown" in template "index.twig" is deprecated since version 1.29 and will throw an exception in 2.0. + */ + public function testRenderBlockWithUndefinedBlock() + { + $twig = new Twig_Environment($this->getMockBuilder('Twig_TemplateTestLoaderInterface')->getMock()); + + $template = new Twig_TemplateTest($twig, false, 'index.twig'); + $template->renderBlock('unknown', array()); + $template->displayBlock('unknown', array()); + } + /** * @dataProvider getTestsDependingOnExtensionAvailability */ @@ -534,6 +550,10 @@ class Twig_TemplateTest extends Twig_Template return parent::getAttribute($object, $item, $arguments, $type, $isDefinedTest, $ignoreStrictCheck); } } + + public function block_name($context, array $blocks = array()) + { + } } class Twig_TemplateArrayAccessObject implements ArrayAccess