mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-21 15:48:42 +00:00
added support for dynamic and conditional inheritance ({% extends some_var %} and {% extends standalone ? minimum : base %})
This commit is contained in:
@@ -5,6 +5,7 @@ Backward incompatibilities:
|
|||||||
* removed the sandboxed attribute of the include tag (use the new sandbox tag instead)
|
* removed the sandboxed attribute of the include tag (use the new sandbox tag instead)
|
||||||
* refactored the Node system (if you have custom nodes, you will have to update them to use the new API)
|
* refactored the Node system (if you have custom nodes, you will have to update them to use the new API)
|
||||||
|
|
||||||
|
* added support for dynamic and conditional inheritance ({% extends some_var %} and {% extends standalone ? "minimum" : "base" %})
|
||||||
* added a grammar sub-framework to ease the creation of custom tags
|
* added a grammar sub-framework to ease the creation of custom tags
|
||||||
* fixed the for tag for large arrays (some loop variables are now only available for arrays and objects that implement the Countable interface)
|
* fixed the for tag for large arrays (some loop variables are now only available for arrays and objects that implement the Countable interface)
|
||||||
* removed the Twig_Resource::resolveMissingFilter() method
|
* removed the Twig_Resource::resolveMissingFilter() method
|
||||||
|
|||||||
@@ -313,6 +313,27 @@ following constructs do the same:
|
|||||||
[twig]
|
[twig]
|
||||||
{% block title page_title|title %}
|
{% block title page_title|title %}
|
||||||
|
|
||||||
|
### Dynamic Inheritance (as of Twig 0.9.7)
|
||||||
|
|
||||||
|
Twig supports dynamic inheritance by using a variable as the base template:
|
||||||
|
|
||||||
|
[twig]
|
||||||
|
{% extends some_var %}
|
||||||
|
|
||||||
|
If the variable evaluates to a `Twig_Template` object, Twig will use it as the
|
||||||
|
parent template.
|
||||||
|
|
||||||
|
### Conditional Inheritance (as of Twig 0.9.7)
|
||||||
|
|
||||||
|
As a matter of fact, the template name can be any valid expression. So, it's
|
||||||
|
also possible to make the inheritance mechanism conditional:
|
||||||
|
|
||||||
|
[twig]
|
||||||
|
{% extends standalone ? "minimum.html" : "base.html" %}
|
||||||
|
|
||||||
|
In this example, the template will extend the "minimum.html" layout template
|
||||||
|
if the `standalone` variable evaluates to `true`, and "base.html" otherwise.
|
||||||
|
|
||||||
Import Context Behavior
|
Import Context Behavior
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
|||||||
+4
-27
@@ -5,40 +5,17 @@ Making a Layout conditional
|
|||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
Working with Ajax means that the same content is sometimes displayed as is,
|
Working with Ajax means that the same content is sometimes displayed as is,
|
||||||
and sometimes decorated with a layout. But as Twig templates are compiled as
|
and sometimes decorated with a layout. As Twig layout template names can be
|
||||||
PHP classes, wrapping an `extends` tag with an `if` tag does not work:
|
any valid expression, you can pass a variable that evaluates to `true` when
|
||||||
|
the request is made via Ajax and choose the layout accordingly:
|
||||||
|
|
||||||
[twig]
|
[twig]
|
||||||
{# this does not work #}
|
{% extends request.ajax ? "base_ajax.html" : "base.html" %}
|
||||||
|
|
||||||
{% if request.ajax %}
|
|
||||||
{% extends "base.html" %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
This is the content to be displayed.
|
This is the content to be displayed.
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
One way to solve this problem is to have two different templates:
|
|
||||||
|
|
||||||
[twig]
|
|
||||||
{# index.html #}
|
|
||||||
{% extends "layout.html" %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
{% include "index_for_ajax.html" %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
|
|
||||||
{# index_for_ajax.html #}
|
|
||||||
This is the content to be displayed.
|
|
||||||
|
|
||||||
Now, the decision to display one of the template is the responsibility of the
|
|
||||||
controller:
|
|
||||||
|
|
||||||
[php]
|
|
||||||
$twig->render($request->isAjax() ? 'index_for_ajax.html' : 'index.html');
|
|
||||||
|
|
||||||
Making an Include dynamic
|
Making an Include dynamic
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class Twig_Node_Block extends Twig_Node
|
|||||||
{
|
{
|
||||||
$compiler
|
$compiler
|
||||||
->addDebugInfo($this)
|
->addDebugInfo($this)
|
||||||
->write(sprintf("public function block_%s(\$context)\n", $this['name']), "{\n")
|
->write(sprintf("public function block_%s(\$context, \$parents)\n", $this['name']), "{\n")
|
||||||
->indent()
|
->indent()
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class Twig_Node_BlockReference extends Twig_Node
|
|||||||
{
|
{
|
||||||
$compiler
|
$compiler
|
||||||
->addDebugInfo($this)
|
->addDebugInfo($this)
|
||||||
->write(sprintf('$this->block_%s($context);'."\n", $this['name']))
|
->write(sprintf("\$this->getBlock('%s', \$context);\n", $this['name']))
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class Twig_Node_Expression_Filter extends Twig_Node_Expression
|
|||||||
if (!isset($filterMap[$name])) {
|
if (!isset($filterMap[$name])) {
|
||||||
throw new Twig_SyntaxError(sprintf('The filter "%s" does not exist', $name), $this->getLine());
|
throw new Twig_SyntaxError(sprintf('The filter "%s" does not exist', $name), $this->getLine());
|
||||||
} else {
|
} else {
|
||||||
$compiler->raw($filterMap[$name]->compile().($filterMap[$name]->needsEnvironment() ? '($this->getEnvironment(), ' : '('));
|
$compiler->raw($filterMap[$name]->compile().($filterMap[$name]->needsEnvironment() ? '($this->env, ' : '('));
|
||||||
}
|
}
|
||||||
$postponed[] = $attrs;
|
$postponed[] = $attrs;
|
||||||
}
|
}
|
||||||
|
|||||||
+59
-21
@@ -19,9 +19,9 @@
|
|||||||
*/
|
*/
|
||||||
class Twig_Node_Module extends Twig_Node
|
class Twig_Node_Module extends Twig_Node
|
||||||
{
|
{
|
||||||
public function __construct(Twig_NodeInterface $body, $extends, Twig_NodeInterface $blocks, Twig_NodeInterface $macros, $filename)
|
public function __construct(Twig_NodeInterface $body, Twig_Node_Expression $parent = null, Twig_NodeInterface $blocks, Twig_NodeInterface $macros, $filename)
|
||||||
{
|
{
|
||||||
parent::__construct(array('body' => $body, 'blocks' => $blocks, 'macros' => $macros), array('filename' => $filename, 'extends' => $extends), 1);
|
parent::__construct(array('parent' => $parent, 'body' => $body, 'blocks' => $blocks, 'macros' => $macros), array('filename' => $filename), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function compile($compiler)
|
public function compile($compiler)
|
||||||
@@ -34,6 +34,10 @@ class Twig_Node_Module extends Twig_Node
|
|||||||
{
|
{
|
||||||
$this->compileClassHeader($compiler);
|
$this->compileClassHeader($compiler);
|
||||||
|
|
||||||
|
if (count($this->blocks)) {
|
||||||
|
$this->compileConstructor($compiler);
|
||||||
|
}
|
||||||
|
|
||||||
$this->compileDisplayHeader($compiler);
|
$this->compileDisplayHeader($compiler);
|
||||||
|
|
||||||
$this->compileDisplayBody($compiler);
|
$this->compileDisplayBody($compiler);
|
||||||
@@ -49,7 +53,7 @@ class Twig_Node_Module extends Twig_Node
|
|||||||
|
|
||||||
protected function compileDisplayBody($compiler)
|
protected function compileDisplayBody($compiler)
|
||||||
{
|
{
|
||||||
if (null !== $this['extends']) {
|
if (null !== $this->parent) {
|
||||||
// remove all but import nodes
|
// remove all but import nodes
|
||||||
foreach ($this->body as $node) {
|
foreach ($this->body as $node) {
|
||||||
if ($node instanceof Twig_Node_Import) {
|
if ($node instanceof Twig_Node_Import) {
|
||||||
@@ -57,9 +61,29 @@ class Twig_Node_Module extends Twig_Node
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->parent instanceof Twig_Node_Expression_Constant) {
|
||||||
|
$compiler
|
||||||
|
->write("\$this->parent = \$this->env->loadTemplate(")
|
||||||
|
->subcompile($this->parent)
|
||||||
|
->raw(");\n")
|
||||||
|
;
|
||||||
|
} else {
|
||||||
|
$compiler
|
||||||
|
->write("\$this->parent = ")
|
||||||
|
->subcompile($this->parent)
|
||||||
|
->raw(";\n")
|
||||||
|
->write("if (!\$this->parent")
|
||||||
|
->raw(" instanceof Twig_Template) {\n")
|
||||||
|
->indent()
|
||||||
|
->write("\$this->parent = \$this->env->loadTemplate(\$this->parent);\n")
|
||||||
|
->outdent()
|
||||||
|
->write("}\n")
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
$compiler
|
$compiler
|
||||||
->raw("\n")
|
->write("\$this->parent->pushBlocks(\$this->blocks);\n")
|
||||||
->write("parent::display(\$context);\n")
|
->write("\$this->parent->display(\$context);\n")
|
||||||
;
|
;
|
||||||
} else {
|
} else {
|
||||||
$compiler->subcompile($this->body);
|
$compiler->subcompile($this->body);
|
||||||
@@ -68,28 +92,42 @@ class Twig_Node_Module extends Twig_Node
|
|||||||
|
|
||||||
protected function compileClassHeader($compiler)
|
protected function compileClassHeader($compiler)
|
||||||
{
|
{
|
||||||
$compiler->write("<?php\n\n");
|
$compiler
|
||||||
|
->write("<?php\n\n")
|
||||||
|
// if the filename contains */, add a blank to avoid a PHP parse error
|
||||||
|
->write("/* ".str_replace('*/', '* /', $this['filename'])." */\n")
|
||||||
|
->write('class '.$compiler->getEnvironment()->getTemplateClass($this['filename']))
|
||||||
|
->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass()))
|
||||||
|
->write("{\n")
|
||||||
|
->indent()
|
||||||
|
;
|
||||||
|
|
||||||
if (null !== $this['extends']) {
|
if (null !== $this->parent) {
|
||||||
|
$compiler->write("protected \$parent;\n\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function compileConstructor($compiler)
|
||||||
|
{
|
||||||
|
$compiler
|
||||||
|
->write("public function __construct(Twig_Environment \$env)\n", "{\n")
|
||||||
|
->indent()
|
||||||
|
->write("parent::__construct(\$env);\n\n")
|
||||||
|
->write("\$this->blocks = array(\n")
|
||||||
|
->indent()
|
||||||
|
;
|
||||||
|
|
||||||
|
foreach ($this->blocks as $name => $node) {
|
||||||
$compiler
|
$compiler
|
||||||
->write('$this->loadTemplate(')
|
->write(sprintf("'%s' => array(array(\$this, 'block_%s')),\n", $name, $name))
|
||||||
->repr($this['extends'])
|
|
||||||
->raw(");\n\n")
|
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
$compiler
|
$compiler
|
||||||
// if the filename contains */, add a blank to avoid a PHP parse error
|
->outdent()
|
||||||
->write("/* ".str_replace('*/', '* /', $this['filename'])." */\n")
|
->write(");\n")
|
||||||
->write('class '.$compiler->getEnvironment()->getTemplateClass($this['filename']))
|
->outdent()
|
||||||
;
|
->write("}\n\n");
|
||||||
|
|
||||||
$parent = null === $this['extends'] ? $compiler->getEnvironment()->getBaseTemplateClass() : $compiler->getEnvironment()->getTemplateClass($this['extends']);
|
|
||||||
|
|
||||||
$compiler
|
|
||||||
->raw(" extends $parent\n")
|
|
||||||
->write("{\n")
|
|
||||||
->indent()
|
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class Twig_Node_Parent extends Twig_Node
|
|||||||
{
|
{
|
||||||
$compiler
|
$compiler
|
||||||
->addDebugInfo($this)
|
->addDebugInfo($this)
|
||||||
->write('parent::block_'.$this['name'].'($context);'."\n")
|
->write("\$this->getParent(\$context, \$parents);\n")
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class Twig_Node_SandboxedModule extends Twig_Node_Module
|
|||||||
|
|
||||||
public function __construct(Twig_Node_Module $node, array $usedFilters, array $usedTags)
|
public function __construct(Twig_Node_Module $node, array $usedFilters, array $usedTags)
|
||||||
{
|
{
|
||||||
parent::__construct($node->body, $node['extends'], $node->blocks, $node->macros, $node['filename'], $node->getLine(), $node->getNodeTag());
|
parent::__construct($node->body, $node->parent, $node->blocks, $node->macros, $node['filename'], $node->getLine(), $node->getNodeTag());
|
||||||
|
|
||||||
$this->usedFilters = $usedFilters;
|
$this->usedFilters = $usedFilters;
|
||||||
$this->usedTags = $usedTags;
|
$this->usedTags = $usedTags;
|
||||||
@@ -32,7 +32,7 @@ class Twig_Node_SandboxedModule extends Twig_Node_Module
|
|||||||
|
|
||||||
protected function compileDisplayBody($compiler)
|
protected function compileDisplayBody($compiler)
|
||||||
{
|
{
|
||||||
if (null === $this['extends']) {
|
if (null === $this->parent) {
|
||||||
$compiler->write("\$this->checkSecurity();\n");
|
$compiler->write("\$this->checkSecurity();\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,10 +54,10 @@ class Twig_Node_SandboxedModule extends Twig_Node_Module
|
|||||||
->write(");\n")
|
->write(");\n")
|
||||||
;
|
;
|
||||||
|
|
||||||
if (null !== $this['extends']) {
|
if (null !== $this->parent) {
|
||||||
$compiler
|
$compiler
|
||||||
->raw("\n")
|
->raw("\n")
|
||||||
->write("parent::checkSecurity();\n")
|
->write("\$this->parent->checkSecurity();\n")
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-11
@@ -12,7 +12,7 @@
|
|||||||
class Twig_Parser implements Twig_ParserInterface
|
class Twig_Parser implements Twig_ParserInterface
|
||||||
{
|
{
|
||||||
protected $stream;
|
protected $stream;
|
||||||
protected $extends;
|
protected $parent;
|
||||||
protected $handlers;
|
protected $handlers;
|
||||||
protected $visitors;
|
protected $visitors;
|
||||||
protected $expressionParser;
|
protected $expressionParser;
|
||||||
@@ -60,7 +60,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->stream = $stream;
|
$this->stream = $stream;
|
||||||
$this->extends = null;
|
$this->parent = null;
|
||||||
$this->blocks = array();
|
$this->blocks = array();
|
||||||
$this->macros = array();
|
$this->macros = array();
|
||||||
$this->blockStack = array();
|
$this->blockStack = array();
|
||||||
@@ -75,7 +75,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_null($this->extends)) {
|
if (null !== $this->parent) {
|
||||||
// check that the body only contains block references and empty text nodes
|
// check that the body only contains block references and empty text nodes
|
||||||
foreach ($body as $node)
|
foreach ($body as $node)
|
||||||
{
|
{
|
||||||
@@ -87,13 +87,9 @@ class Twig_Parser implements Twig_ParserInterface
|
|||||||
throw new Twig_SyntaxError('A template that extends another one cannot have a body', $node->getLine(), $this->stream->getFilename());
|
throw new Twig_SyntaxError('A template that extends another one cannot have a body', $node->getLine(), $this->stream->getFilename());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->blocks as $block) {
|
|
||||||
$block['parent'] = $this->extends;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$node = new Twig_Node_Module($body, $this->extends, new Twig_Node($this->blocks), new Twig_Node($this->macros), $this->stream->getFilename());
|
$node = new Twig_Node_Module($body, $this->parent, new Twig_Node($this->blocks), new Twig_Node($this->macros), $this->stream->getFilename());
|
||||||
|
|
||||||
$traverser = new Twig_NodeTraverser($this->env, $this->visitors);
|
$traverser = new Twig_NodeTraverser($this->env, $this->visitors);
|
||||||
|
|
||||||
@@ -212,12 +208,12 @@ class Twig_Parser implements Twig_ParserInterface
|
|||||||
|
|
||||||
public function getParent()
|
public function getParent()
|
||||||
{
|
{
|
||||||
return $this->extends;
|
return $this->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setParent($extends)
|
public function setParent($parent)
|
||||||
{
|
{
|
||||||
$this->extends = $extends;
|
$this->parent = $parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStream()
|
public function getStream()
|
||||||
|
|||||||
@@ -11,6 +11,36 @@
|
|||||||
*/
|
*/
|
||||||
abstract class Twig_Template extends Twig_Resource implements Twig_TemplateInterface
|
abstract class Twig_Template extends Twig_Resource implements Twig_TemplateInterface
|
||||||
{
|
{
|
||||||
|
protected $blocks;
|
||||||
|
|
||||||
|
public function __construct(Twig_Environment $env)
|
||||||
|
{
|
||||||
|
parent::__construct($env);
|
||||||
|
|
||||||
|
$this->blocks = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getBlock($name, array $context)
|
||||||
|
{
|
||||||
|
return call_user_func($this->blocks[$name][0], $context, array_slice($this->blocks[$name], 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getParent($context, $parents)
|
||||||
|
{
|
||||||
|
return call_user_func($parents[0], $context, array_slice($parents, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pushBlocks($blocks)
|
||||||
|
{
|
||||||
|
foreach ($blocks as $name => $call) {
|
||||||
|
if (!isset($this->blocks[$name])) {
|
||||||
|
$this->blocks[$name] = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->blocks[$name] = array_merge($call, $this->blocks[$name]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the template with the given context and returns it as string.
|
* Renders the template with the given context and returns it as string.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ class Twig_TokenParser_Extends extends Twig_TokenParser
|
|||||||
if (null !== $this->parser->getParent()) {
|
if (null !== $this->parser->getParent()) {
|
||||||
throw new Twig_SyntaxError('Multiple extends tags are forbidden', $token->getLine());
|
throw new Twig_SyntaxError('Multiple extends tags are forbidden', $token->getLine());
|
||||||
}
|
}
|
||||||
$this->parser->setParent($this->parser->getStream()->expect(Twig_Token::STRING_TYPE)->getValue());
|
$this->parser->setParent($this->parser->getExpressionParser()->parseExpression());
|
||||||
|
|
||||||
$this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
|
$this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class Twig_Tests_Node_BlockReferenceTest extends Twig_Tests_Node_TestCase
|
|||||||
public function getTests()
|
public function getTests()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
array(new Twig_Node_BlockReference('foo', 0), '$this->block_foo($context);'),
|
array(new Twig_Node_BlockReference('foo', 0), '$this->getBlock(\'foo\', $context);'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class Twig_Tests_Node_BlockTest extends Twig_Tests_Node_TestCase
|
|||||||
|
|
||||||
return array(
|
return array(
|
||||||
array($node, <<<EOF
|
array($node, <<<EOF
|
||||||
public function block_foo(\$context)
|
public function block_foo(\$context, \$parents)
|
||||||
{
|
{
|
||||||
echo "foo";
|
echo "foo";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ class Twig_Tests_Node_Expression_FilterTest extends Twig_Tests_Node_TestCase
|
|||||||
), array(), 0);
|
), array(), 0);
|
||||||
$node = new Twig_Node_Expression_Filter($expr, $filters, 0);
|
$node = new Twig_Node_Expression_Filter($expr, $filters, 0);
|
||||||
|
|
||||||
$tests[] = array($node, 'twig_lower_filter($this->getEnvironment(), twig_upper_filter($this->getEnvironment(), "foo"), "bar", "foobar")');
|
$tests[] = array($node, 'twig_lower_filter($this->env, twig_upper_filter($this->env, "foo"), "bar", "foobar")');
|
||||||
|
|
||||||
return $tests;
|
return $tests;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,17 +19,17 @@ class Twig_Tests_Node_ModuleTest extends Twig_Tests_Node_TestCase
|
|||||||
public function testConstructor()
|
public function testConstructor()
|
||||||
{
|
{
|
||||||
$body = new Twig_Node_Text('foo', 0);
|
$body = new Twig_Node_Text('foo', 0);
|
||||||
$extends = 'layout.twig';
|
$parent = new Twig_Node_Expression_Constant('layout.twig', 0);
|
||||||
$blocks = new Twig_Node();
|
$blocks = new Twig_Node();
|
||||||
$macros = new Twig_Node();
|
$macros = new Twig_Node();
|
||||||
$filename = 'foo.twig';
|
$filename = 'foo.twig';
|
||||||
$node = new Twig_Node_Module($body, $extends, $blocks, $macros, $filename);
|
$node = new Twig_Node_Module($body, $parent, $blocks, $macros, $filename);
|
||||||
|
|
||||||
$this->assertEquals($body, $node->body);
|
$this->assertEquals($body, $node->body);
|
||||||
$this->assertEquals($blocks, $node->blocks);
|
$this->assertEquals($blocks, $node->blocks);
|
||||||
$this->assertEquals($macros, $node->macros);
|
$this->assertEquals($macros, $node->macros);
|
||||||
|
$this->assertEquals($parent, $node->parent);
|
||||||
$this->assertEquals($filename, $node['filename']);
|
$this->assertEquals($filename, $node['filename']);
|
||||||
$this->assertEquals($extends, $node['extends']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,25 +89,63 @@ EOF
|
|||||||
$import = new Twig_Node_Import(new Twig_Node_Expression_Constant('foo.twig', 0), new Twig_Node_Expression_AssignName('macro', 0), 0);
|
$import = new Twig_Node_Import(new Twig_Node_Expression_Constant('foo.twig', 0), new Twig_Node_Expression_AssignName('macro', 0), 0);
|
||||||
|
|
||||||
$body = new Twig_Node(array($import, new Twig_Node_Text('foo', 0)));
|
$body = new Twig_Node(array($import, new Twig_Node_Text('foo', 0)));
|
||||||
$extends = 'layout.twig';
|
$extends = new Twig_Node_Expression_Constant('layout.twig', 0);
|
||||||
$blocks = new Twig_Node();
|
|
||||||
$macros = new Twig_Node();
|
|
||||||
$filename = 'foo.twig';
|
|
||||||
|
|
||||||
$node = new Twig_Node_Module($body, $extends, $blocks, $macros, $filename);
|
$node = new Twig_Node_Module($body, $extends, $blocks, $macros, $filename);
|
||||||
$tests[] = array($node, <<<EOF
|
$tests[] = array($node, <<<EOF
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
\$this->loadTemplate("layout.twig");
|
|
||||||
|
|
||||||
/* foo.twig */
|
/* foo.twig */
|
||||||
class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends __TwigTemplate_d8fb9d03f55738ff78518e1bc2741faf
|
class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
|
||||||
{
|
{
|
||||||
|
protected \$parent;
|
||||||
|
|
||||||
public function display(array \$context)
|
public function display(array \$context)
|
||||||
{
|
{
|
||||||
\$context['macro'] = \$this->env->loadTemplate("foo.twig", true);
|
\$context['macro'] = \$this->env->loadTemplate("foo.twig", true);
|
||||||
|
\$this->parent = \$this->env->loadTemplate("layout.twig");
|
||||||
|
\$this->parent->pushBlocks(\$this->blocks);
|
||||||
|
\$this->parent->display(\$context);
|
||||||
|
}
|
||||||
|
|
||||||
parent::display(\$context);
|
public function getName()
|
||||||
|
{
|
||||||
|
return "foo.twig";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34_Macro extends Twig_Macro
|
||||||
|
{
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
, $twig);
|
||||||
|
|
||||||
|
$body = new Twig_Node_Text('foo', 0);
|
||||||
|
$extends = new Twig_Node_Expression_Conditional(
|
||||||
|
new Twig_Node_Expression_Constant(true, 0),
|
||||||
|
new Twig_Node_Expression_Constant('foo', 0),
|
||||||
|
new Twig_Node_Expression_Constant('foo', 0),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
$node = new Twig_Node_Module($body, $extends, $blocks, $macros, $filename);
|
||||||
|
$tests[] = array($node, <<<EOF
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/* foo.twig */
|
||||||
|
class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
|
||||||
|
{
|
||||||
|
protected \$parent;
|
||||||
|
|
||||||
|
public function display(array \$context)
|
||||||
|
{
|
||||||
|
\$this->parent = (true) ? ("foo") : ("foo");
|
||||||
|
if (!\$this->parent instanceof Twig_Template) {
|
||||||
|
\$this->parent = \$this->env->loadTemplate(\$this->parent);
|
||||||
|
}
|
||||||
|
\$this->parent->pushBlocks(\$this->blocks);
|
||||||
|
\$this->parent->display(\$context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName()
|
public function getName()
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class Twig_Tests_Node_ParentTest extends Twig_Tests_Node_TestCase
|
|||||||
public function getTests()
|
public function getTests()
|
||||||
{
|
{
|
||||||
$tests = array();
|
$tests = array();
|
||||||
$tests[] = array(new Twig_Node_Parent('foo', 0), 'parent::block_foo($context);');
|
$tests[] = array(new Twig_Node_Parent('foo', 0), '$this->getParent($context, $parents);');
|
||||||
|
|
||||||
return $tests;
|
return $tests;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,18 +19,18 @@ class Twig_Tests_Node_SandboxedModuleTest extends Twig_Tests_Node_TestCase
|
|||||||
public function testConstructor()
|
public function testConstructor()
|
||||||
{
|
{
|
||||||
$body = new Twig_Node_Text('foo', 0);
|
$body = new Twig_Node_Text('foo', 0);
|
||||||
$extends = 'layout.twig';
|
$parent = new Twig_Node_Expression_Constant('layout.twig', 0);
|
||||||
$blocks = new Twig_Node();
|
$blocks = new Twig_Node();
|
||||||
$macros = new Twig_Node();
|
$macros = new Twig_Node();
|
||||||
$filename = 'foo.twig';
|
$filename = 'foo.twig';
|
||||||
$node = new Twig_Node_Module($body, $extends, $blocks, $macros, $filename);
|
$node = new Twig_Node_Module($body, $parent, $blocks, $macros, $filename);
|
||||||
$node = new Twig_Node_SandboxedModule($node, array('for'), array('upper'));
|
$node = new Twig_Node_SandboxedModule($node, array('for'), array('upper'));
|
||||||
|
|
||||||
$this->assertEquals($body, $node->body);
|
$this->assertEquals($body, $node->body);
|
||||||
$this->assertEquals($blocks, $node->blocks);
|
$this->assertEquals($blocks, $node->blocks);
|
||||||
$this->assertEquals($macros, $node->macros);
|
$this->assertEquals($macros, $node->macros);
|
||||||
|
$this->assertEquals($parent, $node->parent);
|
||||||
$this->assertEquals($filename, $node['filename']);
|
$this->assertEquals($filename, $node['filename']);
|
||||||
$this->assertEquals($extends, $node['extends']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,7 +92,7 @@ EOF
|
|||||||
, $twig);
|
, $twig);
|
||||||
|
|
||||||
$body = new Twig_Node_Text('foo', 0);
|
$body = new Twig_Node_Text('foo', 0);
|
||||||
$extends = 'layout.twig';
|
$extends = new Twig_Node_Expression_Constant('layout.twig', 0);
|
||||||
$blocks = new Twig_Node();
|
$blocks = new Twig_Node();
|
||||||
$macros = new Twig_Node();
|
$macros = new Twig_Node();
|
||||||
$filename = 'foo.twig';
|
$filename = 'foo.twig';
|
||||||
@@ -103,15 +103,16 @@ EOF
|
|||||||
$tests[] = array($node, <<<EOF
|
$tests[] = array($node, <<<EOF
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
\$this->loadTemplate("layout.twig");
|
|
||||||
|
|
||||||
/* foo.twig */
|
/* foo.twig */
|
||||||
class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends __TwigTemplate_d8fb9d03f55738ff78518e1bc2741faf
|
class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
|
||||||
{
|
{
|
||||||
|
protected \$parent;
|
||||||
|
|
||||||
public function display(array \$context)
|
public function display(array \$context)
|
||||||
{
|
{
|
||||||
|
\$this->parent = \$this->env->loadTemplate("layout.twig");
|
||||||
parent::display(\$context);
|
\$this->parent->pushBlocks(\$this->blocks);
|
||||||
|
\$this->parent->display(\$context);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function checkSecurity() {
|
protected function checkSecurity() {
|
||||||
@@ -120,7 +121,7 @@ class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends __TwigTemplate_d8f
|
|||||||
array('for')
|
array('for')
|
||||||
);
|
);
|
||||||
|
|
||||||
parent::checkSecurity();
|
\$this->parent->checkSecurity();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName()
|
public function getName()
|
||||||
|
|||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
--TEST--
|
||||||
|
"extends" tag
|
||||||
|
--TEMPLATE--
|
||||||
|
{% extends standalone ? foo : 'bar.twig' %}
|
||||||
|
|
||||||
|
{% block content %}{% parent %}FOO{% endblock %}
|
||||||
|
--TEMPLATE(foo.twig)--
|
||||||
|
{% block content %}FOO{% endblock %}
|
||||||
|
--TEMPLATE(bar.twig)--
|
||||||
|
{% block content %}BAR{% endblock %}
|
||||||
|
--DATA--
|
||||||
|
return array('foo' => 'foo.twig', 'standalone' => true)
|
||||||
|
--EXPECT--
|
||||||
|
FOOFOO
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
--TEST--
|
||||||
|
"extends" tag
|
||||||
|
--TEMPLATE--
|
||||||
|
{% extends foo %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
FOO
|
||||||
|
{% endblock %}
|
||||||
|
--TEMPLATE(foo.twig)--
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
--DATA--
|
||||||
|
return array('foo' => 'foo.twig')
|
||||||
|
--EXPECT--
|
||||||
|
FOO
|
||||||
Reference in New Issue
Block a user