* the odd and even filters are now tests:
{{ foo|odd }} must now be written {{ foo is odd }}
+ * the implementation of template inheritance has been rewritten
+ (blocks can now be called individually and still work with inheritance)
* fixed error handling for if tag when a syntax error occurs within a subparse process
* added a way to implement custom logic for resolving token parsers given a tag name
* fixed js escaper to be stricter (now uses a whilelist-based js escaper)
{
$compiler
->addDebugInfo($this)
- ->write(sprintf("public function block_%s(\$context, \$parents)\n", $this['name']), "{\n")
+ ->write(sprintf("public function block_%s(\$context, array \$blocks = array())\n", $this['name']), "{\n")
->indent()
;
{
$compiler
->addDebugInfo($this)
- ->write(sprintf("\$this->getBlock('%s', \$context);\n", $this['name']))
+ ->write(sprintf("\$this->getBlock('%s', \$context, \$blocks);\n", $this['name']))
;
}
}
$this->compileConstructor($compiler);
}
+ $this->compileGetParent($compiler);
+
$this->compileDisplayHeader($compiler);
$this->compileDisplayBody($compiler);
$this->compileClassFooter($compiler);
}
+ protected function compileGetParent($compiler)
+ {
+ if (null === $this->parent) {
+ return;
+ }
+
+ $compiler
+ ->write("public function getParent(array \$context)\n", "{\n")
+ ->indent()
+ ->write("if (null === \$this->parent) {\n")
+ ->indent();
+ ;
+
+ 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
+ ->outdent()
+ ->write("}\n\n")
+ ->write("return \$this->parent;\n")
+ ->outdent()
+ ->write("}\n\n")
+ ;
+ }
+
protected function compileDisplayBody($compiler)
{
if (null !== $this->parent) {
}
$compiler
- ->write("if (null === \$this->parent) {\n")
- ->indent();
- ;
-
- if ($this->parent instanceof Twig_Node_Expression_Constant) {
- $compiler
- ->write("\$this->parent = clone \$this->env->loadTemplate(")
- ->subcompile($this->parent)
- ->raw(");\n")
- ;
- } else {
- $compiler
- ->write("\$parent = ")
- ->subcompile($this->parent)
- ->raw(";\n")
- ->write("if (!\$parent")
- ->raw(" instanceof Twig_Template) {\n")
- ->indent()
- ->write("\$parent = \$this->env->loadTemplate(\$parent);\n")
- ->outdent()
- ->write("}\n")
- ->write("\$this->parent = clone \$parent;\n")
- ;
- }
-
- $compiler
- ->write("\$this->parent->pushBlocks(\$this->blocks);\n")
- ->outdent()
- ->write("}\n")
- ->write("\$this->parent->display(\$context);\n")
+ ->write("\$this->getParent(\$context)->display(\$context, array_merge(\$this->blocks, \$blocks));\n")
;
} else {
$compiler->subcompile($this->body);
foreach ($this->blocks as $name => $node) {
$compiler
- ->write(sprintf("'%s' => array(array(\$this, 'block_%s')),\n", $name, $name))
+ ->write(sprintf("'%s' => array(\$this, 'block_%s'),\n", $name, $name))
;
}
protected function compileDisplayHeader($compiler)
{
$compiler
- ->write("public function display(array \$context)\n", "{\n")
+ ->write("public function display(array \$context, array \$blocks = array())\n", "{\n")
->indent()
;
}
{
$compiler
->addDebugInfo($this)
- ->write("\$this->getParent(\$context, \$parents);\n")
+ ->write("\$this->getParentBlock(")
+ ->string($this['name'])
+ ->raw(", \$context, \$blocks);\n")
;
}
}
$this->blocks = array();
}
- public function __clone()
- {
- foreach ($this->blocks as $name => $calls) {
- foreach ($calls as $i => $call) {
- $this->blocks[$name][$i][0] = $this;
- }
- }
- }
-
public function getEnvironment()
{
return $this->env;
}
- public function getBlock($name, array $context)
+ public function getParent(array $context)
{
- return call_user_func($this->blocks[$name][0], $context, array_slice($this->blocks[$name], 1));
+ return false;
}
- public function hasBlock($name)
+ public function getParentBlock($name, array $context, array $blocks = array())
{
- return isset($this->blocks[$name][0]);
+ if (false !== $parent = $this->getParent($context)) {
+ return $parent->getBlock($name, $context, $blocks);
+ } else {
+ throw new \LogicException('This template has no parent.');
+ }
}
- protected function getParent($context, $parents)
+ public function getBlock($name, array $context, array $blocks = array())
{
- return call_user_func($parents[0], $context, array_slice($parents, 1));
+ if (isset($blocks[$name])) {
+ $b = $blocks;
+ unset($b[$name]);
+ return call_user_func($blocks[$name], $context, $b);
+ } elseif (isset($this->blocks[$name])) {
+ return call_user_func($this->blocks[$name], $context, $blocks);
+ }
+
+ if (false !== $parent = $this->getParent($context)) {
+ return $parent->getBlock($name, $context, array_merge($this->blocks, $blocks));
+ }
}
- public function pushBlocks($blocks)
+ public function hasBlock($name)
{
- foreach ($blocks as $name => $call) {
- if (!isset($this->blocks[$name])) {
- $this->blocks[$name] = array();
- }
+ return isset($this->blocks[$name]);
+ }
- $this->blocks[$name] = array_merge($call, $this->blocks[$name]);
- }
+ public function getBlockNames()
+ {
+ return array_keys($this->blocks);
}
/**
public function getTests()
{
return array(
- array(new Twig_Node_BlockReference('foo', 0), '$this->getBlock(\'foo\', $context);'),
+ array(new Twig_Node_BlockReference('foo', 0), '$this->getBlock(\'foo\', $context, $blocks);'),
);
}
}
return array(
array($node, <<<EOF
-public function block_foo(\$context, \$parents)
+public function block_foo(\$context, array \$blocks = array())
{
echo "foo";
}
/* foo.twig */
class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
{
- public function display(array \$context)
+ public function display(array \$context, array \$blocks = array())
{
echo "foo";
}
{
protected \$parent;
- public function display(array \$context)
+ public function getParent(array \$context)
{
- \$context['macro'] = \$this->env->loadTemplate("foo.twig", true);
if (null === \$this->parent) {
- \$this->parent = clone \$this->env->loadTemplate("layout.twig");
- \$this->parent->pushBlocks(\$this->blocks);
+ \$this->parent = \$this->env->loadTemplate("layout.twig");
}
- \$this->parent->display(\$context);
+
+ return \$this->parent;
+ }
+
+ public function display(array \$context, array \$blocks = array())
+ {
+ \$context['macro'] = \$this->env->loadTemplate("foo.twig", true);
+ \$this->getParent(\$context)->display(\$context, array_merge(\$this->blocks, \$blocks));
}
}
{
protected \$parent;
- public function display(array \$context)
+ public function getParent(array \$context)
{
if (null === \$this->parent) {
- \$parent = (true) ? ("foo") : ("foo");
- if (!\$parent instanceof Twig_Template) {
- \$parent = \$this->env->loadTemplate(\$parent);
+ \$this->parent = (true) ? ("foo") : ("foo");
+ if (!\$this->parent instanceof Twig_Template) {
+ \$this->parent = \$this->env->loadTemplate(\$this->parent);
}
- \$this->parent = clone \$parent;
- \$this->parent->pushBlocks(\$this->blocks);
}
- \$this->parent->display(\$context);
+
+ return \$this->parent;
+ }
+
+ public function display(array \$context, array \$blocks = array())
+ {
+ \$this->getParent(\$context)->display(\$context, array_merge(\$this->blocks, \$blocks));
}
}
public function getTests()
{
$tests = array();
- $tests[] = array(new Twig_Node_Parent('foo', 0), '$this->getParent($context, $parents);');
+ $tests[] = array(new Twig_Node_Parent('foo', 0), '$this->getParentBlock("foo", $context, $blocks);');
return $tests;
}
/* foo.twig */
class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
{
- public function display(array \$context)
+ public function display(array \$context, array \$blocks = array())
{
\$this->checkSecurity();
echo "foo";
{
protected \$parent;
- public function display(array \$context)
+ public function getParent(array \$context)
{
if (null === \$this->parent) {
- \$this->parent = clone \$this->env->loadTemplate("layout.twig");
- \$this->parent->pushBlocks(\$this->blocks);
+ \$this->parent = \$this->env->loadTemplate("layout.twig");
}
- \$this->parent->display(\$context);
+
+ return \$this->parent;
+ }
+
+ public function display(array \$context, array \$blocks = array())
+ {
+ \$this->getParent(\$context)->display(\$context, array_merge(\$this->blocks, \$blocks));
}
protected function checkSecurity() {