Skip to content

Commit

Permalink
feature #2245 added support for a custom template on the block() func…
Browse files Browse the repository at this point in the history
…tion (fabpot)

This PR was merged into the 1.x branch.

Discussion
----------

added support for a custom template on the block() function

`block()` allows one to render a block of the current template.

This PR adds the possibility to use `block()` to render a block of another template:

```twig
{{ block('footer', template_name) }}
```

As it uses the same logic as for the regular `block()`, you can also use it in a test:

```twig
{% if block('footer', template_name) is defined %}
    ...
{% endif %}
```

This removes the needs to use the internal `Twig_Template::renderBlock()` method in the Symfony Web Profiler for instance. And combined with #2236, it allows us to really mark the whole `Twig_Template` class as being internal.

I'm aware that #1302 asked for being able to pass a context to `block()` (implemented in #1433), but I prefer not to in favor of adding the `with` tag (see #719 and #1054).

When the `with` will be implemented, the code in the Symfony Web Profiler will become something along the lines of:

```twig
        {% with {
            'collector': profile.getcollector(name),
            'profiler_url': profiler_url,
            'token': profile.token,
            'name': name
          } %}
            {{ block('toolbar', template) }}
        {% endwith %}
```

Commits
-------

5ed59be added support for a custom template on the block() function
  • Loading branch information
fabpot committed Nov 13, 2016
2 parents bbd30b0 + 5ed59be commit 02b084e
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
@@ -1,5 +1,6 @@
* 1.28.0 (2016-XX-XX)

* added support for a custom template on the block() function
* added "is defined" support for block() and constant()
* optimized the way attributes are fetched

Expand Down
16 changes: 15 additions & 1 deletion doc/functions/block.rst
Expand Up @@ -3,7 +3,10 @@

.. versionadded: 1.28
Using ``block`` with the ``defined`` test was added in Twig 1.28.
.. versionadded: 1.28
Support for the template argument was added in Twig 1.28.
When a template uses inheritance and if you want to print a block multiple
times, use the ``block`` function:

Expand All @@ -15,6 +18,13 @@ times, use the ``block`` function:
{% block body %}{% endblock %}
The ``block`` function can also be used to display one block of another
template:

.. code-block:: jinja
{{ block("title", "common_blocks.twig") }}
Use the ``defined`` test to check if a block exists in the context of the
current template:

Expand All @@ -24,4 +34,8 @@ current template:
...
{% endif %}
{% if block("footer", "common_blocks.twig") is defined %}
...
{% endif %}
.. seealso:: :doc:`extends<../tags/extends>`, :doc:`parent<../functions/parent>`
2 changes: 1 addition & 1 deletion lib/Twig/ExpressionParser.php
Expand Up @@ -349,7 +349,7 @@ public function getFunctionNode($name, $line)
throw new Twig_Error_Syntax('The "block" function takes one argument (the block name).', $line, $this->parser->getStream()->getSourceContext()->getName());
}

return new Twig_Node_Expression_BlockReference($args->getNode(0), $line);
return new Twig_Node_Expression_BlockReference($args->getNode(0), count($args) > 1 ? $args->getNode(1) : null, $line);
case 'attribute':
$args = $this->parseArguments();
if (count($args) < 2) {
Expand Down
47 changes: 37 additions & 10 deletions lib/Twig/Node/Expression/BlockReference.php
Expand Up @@ -17,16 +17,23 @@
*/
class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
{
public function __construct(Twig_NodeInterface $name, $lineno, $tag = null)
/**
* @param Twig_Node|null $template
*/
public function __construct(Twig_NodeInterface $name, $template = null, $lineno, $tag = null)
{
if (is_bool($lineno)) {
if (is_bool($template)) {
@trigger_error(sprintf('The %s method "$asString" argument is deprecated since version 1.28 and will be removed in 2.0.', __METHOD__), E_USER_DEPRECATED);

$lineno = $tag;
$tag = func_num_args() > 3 ? func_get_arg(3) : null;
$template = null;
}

parent::__construct(array('name' => $name), array('is_defined_test' => false, 'output' => false), $lineno, $tag);
$nodes = array('name' => $name);
if (null !== $template) {
$nodes['template'] = $template;
}

parent::__construct($nodes, array('is_defined_test' => false, 'output' => false), $lineno, $tag);
}

public function compile(Twig_Compiler $compiler)
Expand All @@ -39,19 +46,39 @@ public function compile(Twig_Compiler $compiler)
;
} else {
if ($this->getAttribute('output')) {
$compiler
->addDebugInfo($this)
->write('$this->displayBlock(')
$compiler->addDebugInfo($this);

$this
->compileTemplateCall($compiler)
->raw('->displayBlock(')
->subcompile($this->getNode('name'))
->raw(", \$context, \$blocks);\n")
;
} else {
$compiler
->raw('$this->renderBlock(')
$this
->compileTemplateCall($compiler)
->raw('->renderBlock(')
->subcompile($this->getNode('name'))
->raw(', $context, $blocks)')
;
}
}
}

private function compileTemplateCall(Twig_Compiler $compiler)
{
if (!$this->hasNode('template')) {
return $compiler->write('$this');
}

return $compiler
->write('$this->loadTemplate(')
->subcompile($this->getNode('template'))
->raw(', ')
->repr($this->getTemplateName())
->raw(', ')
->repr($this->getTemplateLine())
->raw(')')
;
}
}
2 changes: 1 addition & 1 deletion lib/Twig/TokenParser/Filter.php
Expand Up @@ -23,7 +23,7 @@ class Twig_TokenParser_Filter extends Twig_TokenParser
public function parse(Twig_Token $token)
{
$name = $this->parser->getVarName();
$ref = new Twig_Node_Expression_BlockReference(new Twig_Node_Expression_Constant($name, $token->getLine()), $token->getLine(), $this->getTag());
$ref = new Twig_Node_Expression_BlockReference(new Twig_Node_Expression_Constant($name, $token->getLine()), null, $token->getLine(), $this->getTag());

$filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref, $this->getTag());
$this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
Expand Down

0 comments on commit 02b084e

Please sign in to comment.