diff --git a/CHANGELOG b/CHANGELOG
index 83361a98b..d568ae41c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -17,7 +17,15 @@
* improved the performance of the filesystem loader
* removed features that were deprecated in 1.x
-* 1.28.0 (2016-XX-XX)
+* 1.28.2 (2016-XX-XX)
+
+ * n/a
+
+* 1.28.1 (2016-11-18)
+
+ * fixed block() function when used with a template argument
+
+* 1.28.0 (2016-11-17)
* added support for the PHP 7 null coalescing operator for the ?? Twig implementation
* exposed a way to access template data and methods in a portable way
diff --git a/composer.json b/composer.json
index 03c9046a2..f2cda779e 100644
--- a/composer.json
+++ b/composer.json
@@ -31,7 +31,7 @@
"symfony/polyfill-mbstring": "~1.0"
},
"require-dev": {
- "symfony/phpunit-bridge": "~2.7",
+ "symfony/phpunit-bridge": "~3.2@dev",
"symfony/debug": "~2.7"
},
"autoload": {
diff --git a/doc/recipes.rst b/doc/recipes.rst
index a05095d04..40c0efa26 100644
--- a/doc/recipes.rst
+++ b/doc/recipes.rst
@@ -510,18 +510,18 @@ include in your templates:
``interpolateProvider`` service, for instance at the module initialization
time:
- ```js
- angular.module('myApp', []).config(function($interpolateProvider) {
- $interpolateProvider.startSymbol('{[').endSymbol(']}');
- });
- ```
+ ..code-block:: javascript
+
+ angular.module('myApp', []).config(function($interpolateProvider) {
+ $interpolateProvider.startSymbol('{[').endSymbol(']}');
+ });
* For Twig, change the delimiters via the ``tag_variable`` Lexer option:
- ```php
- $env->setLexer(new Twig_Lexer($env, array(
- 'tag_variable' => array('{[', ']}'),
- )));
- ```
+ ..code-block:: php
+
+ $env->setLexer(new Twig_Lexer($env, array(
+ 'tag_variable' => array('{[', ']}'),
+ )));
.. _callback: http://www.php.net/manual/en/function.is-callable.php
diff --git a/doc/tags/with.rst b/doc/tags/with.rst
index c40856e27..41cb72713 100644
--- a/doc/tags/with.rst
+++ b/doc/tags/with.rst
@@ -32,6 +32,8 @@ is equivalent to the following one:
By default, the inner scope has access to the outer scope context; you can
disable this behavior by appending the ``only`` keyword:
+.. code-block:: jinja
+
{% set bar = 'bar' %}
{% with { foo: 42 } only %}
{# only foo is defined #}
diff --git a/lib/Twig/Node/Expression/BlockReference.php b/lib/Twig/Node/Expression/BlockReference.php
index ad41c3a4e..8c921b00c 100644
--- a/lib/Twig/Node/Expression/BlockReference.php
+++ b/lib/Twig/Node/Expression/BlockReference.php
@@ -30,46 +30,53 @@ class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
public function compile(Twig_Compiler $compiler)
{
if ($this->getAttribute('is_defined_test')) {
- $compiler
- ->raw('$this->hasBlock(')
- ->subcompile($this->getNode('name'))
- ->raw(', $context, $blocks)')
- ;
+ $this->compileTemplateCall($compiler, 'hasBlock');
} else {
if ($this->getAttribute('output')) {
$compiler->addDebugInfo($this);
$this
- ->compileTemplateCall($compiler)
- ->raw('->displayBlock(')
- ->subcompile($this->getNode('name'))
- ->raw(", \$context, \$blocks);\n")
- ;
+ ->compileTemplateCall($compiler, 'displayBlock')
+ ->raw(";\n");
} else {
- $this
- ->compileTemplateCall($compiler)
- ->raw('->renderBlock(')
- ->subcompile($this->getNode('name'))
- ->raw(', $context, $blocks)')
- ;
+ $this->compileTemplateCall($compiler, 'renderBlock');
}
}
}
- private function compileTemplateCall(Twig_Compiler $compiler)
+ private function compileTemplateCall(Twig_Compiler $compiler, $method)
{
if (!$this->hasNode('template')) {
- return $compiler->write('$this');
+ $compiler->write('$this');
+ } else {
+ $compiler
+ ->write('$this->loadTemplate(')
+ ->subcompile($this->getNode('template'))
+ ->raw(', ')
+ ->repr($this->getTemplateName())
+ ->raw(', ')
+ ->repr($this->getTemplateLine())
+ ->raw(')')
+ ;
}
- return $compiler
- ->write('$this->loadTemplate(')
- ->subcompile($this->getNode('template'))
- ->raw(', ')
- ->repr($this->getTemplateName())
- ->raw(', ')
- ->repr($this->getTemplateLine())
- ->raw(')')
- ;
+ $compiler->raw(sprintf('->%s', $method));
+ $this->compileBlockArguments($compiler);
+
+ return $compiler;
+ }
+
+ private function compileBlockArguments(Twig_Compiler $compiler)
+ {
+ $compiler
+ ->raw('(')
+ ->subcompile($this->getNode('name'))
+ ->raw(', $context');
+
+ if (!$this->hasNode('template')) {
+ $compiler->raw(', $blocks');
+ }
+
+ return $compiler->raw(')');
}
}
diff --git a/lib/Twig/TemplateWrapper.php b/lib/Twig/TemplateWrapper.php
index 7325dcd3c..2db61cdad 100644
--- a/lib/Twig/TemplateWrapper.php
+++ b/lib/Twig/TemplateWrapper.php
@@ -87,20 +87,6 @@ final class Twig_TemplateWrapper
* @return string The rendered block
*/
public function renderBlock($name, $context = array())
- {
- ob_start();
- $this->displayBlock($name, $context);
-
- return ob_get_clean();
- }
-
- /**
- * Displays a template block.
- *
- * @param string $name The block name to render
- * @param array $context An array of parameters to pass to the template
- */
- public function displayBlock($name, $context = array())
{
$context = $this->env->mergeGlobals($context);
$level = ob_get_level();
@@ -124,6 +110,17 @@ final class Twig_TemplateWrapper
return ob_get_clean();
}
+ /**
+ * Displays a template block.
+ *
+ * @param string $name The block name to render
+ * @param array $context An array of parameters to pass to the template
+ */
+ public function displayBlock($name, $context = array())
+ {
+ $this->template->displayBlock($name, $this->env->mergeGlobals($context));
+ }
+
/**
* @return Twig_Source
*/
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 6f6d1d25a..ce7732785 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -17,6 +17,14 @@
+
+
+
+
+
+
+
+
./lib/Twig/
diff --git a/test/Twig/Tests/EnvironmentTest.php b/test/Twig/Tests/EnvironmentTest.php
index bcd0eb1dd..66d97df57 100644
--- a/test/Twig/Tests/EnvironmentTest.php
+++ b/test/Twig/Tests/EnvironmentTest.php
@@ -485,6 +485,7 @@ class Twig_Tests_EnvironmentTest_Runtime
}
}
+// to be removed in 2.0
interface Twig_EnvironmentTestLoaderInterface extends Twig_LoaderInterface, Twig_SourceContextLoaderInterface
{
}
diff --git a/test/Twig/Tests/Fixtures/functions/block_with_template.test b/test/Twig/Tests/Fixtures/functions/block_with_template.test
new file mode 100644
index 000000000..8305eb67f
--- /dev/null
+++ b/test/Twig/Tests/Fixtures/functions/block_with_template.test
@@ -0,0 +1,22 @@
+--TEST--
+"block" function with a template argument
+--TEMPLATE--
+{{ block('foo', 'included.twig') }}
+{{ block('foo', included_loaded) }}
+{{ block('foo', included_loaded_internal) }}
+{% set output = block('foo', 'included.twig') %}
+{{ output }}
+{% block foo %}NOT FOO{% endblock %}
+--TEMPLATE(included.twig)--
+{% block foo %}FOO{% endblock %}
+--DATA--
+return array(
+ 'included_loaded' => $twig->load('included.twig'),
+ 'included_loaded_internal' => $twig->loadTemplate('included.twig'),
+)
+--EXPECT--
+FOO
+FOO
+FOO
+FOO
+NOT FOO
diff --git a/test/Twig/Tests/Fixtures/tests/defined_for_blocks_with_template.test b/test/Twig/Tests/Fixtures/tests/defined_for_blocks_with_template.test
new file mode 100644
index 000000000..2c651657e
--- /dev/null
+++ b/test/Twig/Tests/Fixtures/tests/defined_for_blocks_with_template.test
@@ -0,0 +1,17 @@
+--TEST--
+"defined" support for blocks with a template argument
+--TEMPLATE--
+{{ block('foo', 'included.twig') is defined ? 'ok' : 'ko' }}
+{{ block('foo', included_loaded) is defined ? 'ok' : 'ko' }}
+{{ block('foo', included_loaded_internal) is defined ? 'ok' : 'ko' }}
+--TEMPLATE(included.twig)--
+{% block foo %}FOO{% endblock %}
+--DATA--
+return array(
+ 'included_loaded' => $twig->load('included.twig'),
+ 'included_loaded_internal' => $twig->loadTemplate('included.twig'),
+)
+--EXPECT--
+ok
+ok
+ok
diff --git a/test/Twig/Tests/NativeExtensionTest.php b/test/Twig/Tests/NativeExtensionTest.php
index 942aff9e3..a692be1f3 100644
--- a/test/Twig/Tests/NativeExtensionTest.php
+++ b/test/Twig/Tests/NativeExtensionTest.php
@@ -11,6 +11,9 @@
class Twig_Tests_NativeExtensionTest extends PHPUnit_Framework_TestCase
{
+ /**
+ * @requires PHP 5.3
+ */
public function testGetProperties()
{
if (defined('HHVM_VERSION')) {
diff --git a/test/Twig/Tests/TemplateTest.php b/test/Twig/Tests/TemplateTest.php
index ff682f520..1fd67304d 100644
--- a/test/Twig/Tests/TemplateTest.php
+++ b/test/Twig/Tests/TemplateTest.php
@@ -350,9 +350,9 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
// tests when input is not an array or object
$tests = array_merge($tests, array(
- array(false, null, 42, 'a', array(), $anyType, false, 'Impossible to access an attribute ("a") on a integer variable ("42").'),
- array(false, null, 'string', 'a', array(), $anyType, false, 'Impossible to access an attribute ("a") on a string variable ("string").'),
- array(false, null, array(), 'a', array(), $anyType, false, 'Key "a" does not exist as the array is empty.'),
+ array(false, null, 42, 'a', array(), $anyType, false, 'Impossible to access an attribute ("a") on a integer variable ("42") in "index.twig".'),
+ array(false, null, 'string', 'a', array(), $anyType, false, 'Impossible to access an attribute ("a") on a string variable ("string") in "index.twig".'),
+ array(false, null, array(), 'a', array(), $anyType, false, 'Key "a" does not exist as the array is empty in "index.twig".'),
));
// add twig_template_get_attributes tests
@@ -372,12 +372,14 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
class Twig_TemplateTest extends Twig_Template
{
protected $useExtGetAttribute = false;
+ private $name;
- public function __construct(Twig_Environment $env, $useExtGetAttribute = false)
+ public function __construct(Twig_Environment $env, $useExtGetAttribute = false, $name = 'index.twig')
{
parent::__construct($env);
$this->useExtGetAttribute = $useExtGetAttribute;
self::$cache = array();
+ $this->name = $name;
}
public function getZero()
@@ -402,6 +404,7 @@ class Twig_TemplateTest extends Twig_Template
public function getTemplateName()
{
+ return $this->name;
}
public function getDebugInfo()
@@ -409,13 +412,9 @@ class Twig_TemplateTest extends Twig_Template
return array();
}
- public function getSource()
- {
- return '';
- }
-
protected function doGetParent(array $context)
{
+ return false;
}
protected function doDisplay(array $context, array $blocks = array())
@@ -658,3 +657,8 @@ class CExtDisablingNodeVisitor implements Twig_NodeVisitorInterface
return 0;
}
}
+
+// to be removed in 2.0
+interface Twig_TemplateTestLoaderInterface extends Twig_LoaderInterface, Twig_SourceContextLoaderInterface
+{
+}
diff --git a/test/Twig/Tests/TemplateWrapperTest.php b/test/Twig/Tests/TemplateWrapperTest.php
index fbc4b4a20..9cd1ced9a 100644
--- a/test/Twig/Tests/TemplateWrapperTest.php
+++ b/test/Twig/Tests/TemplateWrapperTest.php
@@ -35,4 +35,30 @@ class Twig_Tests_TemplateWrapperTest extends PHPUnit_Framework_TestCase
$this->assertTrue($wrapper->hasBlock('extended'));
$this->assertEquals(array('foo', 'extended'), $wrapper->getBlockNames());
}
+
+ public function testRenderBlock()
+ {
+ $twig = new Twig_Environment(new Twig_Loader_Array(array(
+ 'index' => '{% block foo %}{{ foo }}{{ bar }}{% endblock %}',
+ )));
+ $twig->addGlobal('bar', 'BAR');
+
+ $wrapper = new Twig_TemplateWrapper($twig, $twig->loadTemplate('index'));
+ $this->assertEquals('FOOBAR', $wrapper->renderBlock('foo', array('foo' => 'FOO')));
+ }
+
+ public function testDisplayBlock()
+ {
+ $twig = new Twig_Environment(new Twig_Loader_Array(array(
+ 'index' => '{% block foo %}{{ foo }}{{ bar }}{% endblock %}',
+ )));
+ $twig->addGlobal('bar', 'BAR');
+
+ $wrapper = new Twig_TemplateWrapper($twig, $twig->loadTemplate('index'));
+
+ ob_start();
+ $wrapper->displayBlock('foo', array('foo' => 'FOO'));
+
+ $this->assertEquals('FOOBAR', ob_get_clean());
+ }
}