initial import

This commit is contained in:
Alchemy
2011-02-16 16:09:48 +01:00
parent 399a584b6f
commit 339d23c06d
5539 changed files with 2028637 additions and 1 deletions

View File

@@ -0,0 +1,40 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents an autoescape node.
*
* The value is the escaping strategy (can be html, js, ...)
*
* The true value is equivalent to html.
*
* If autoescaping is disabled, then the value is false.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Twig_Node_AutoEscape extends Twig_Node
{
public function __construct($value, Twig_NodeInterface $body, $lineno, $tag = 'autoescape')
{
parent::__construct(array('body' => $body), array('value' => $value), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$compiler->subcompile($this->getNode('body'));
}
}

45
lib/classes/Twig/Node/Block.php Executable file
View File

@@ -0,0 +1,45 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a block node.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Twig_Node_Block extends Twig_Node
{
public function __construct($name, Twig_NodeInterface $body, $lineno, $tag = null)
{
parent::__construct(array('body' => $body), array('name' => $name), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$compiler
->addDebugInfo($this)
->write(sprintf("public function block_%s(\$context, array \$blocks = array())\n", $this->getAttribute('name')), "{\n")
->indent()
;
$compiler
->subcompile($this->getNode('body'))
->outdent()
->write("}\n\n")
;
}
}

View File

@@ -0,0 +1,38 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a block call node.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Twig_Node_BlockReference extends Twig_Node
{
public function __construct($name, $lineno, $tag = null)
{
parent::__construct(array(), array('name' => $name), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$compiler
->addDebugInfo($this)
->write(sprintf("\$this->getBlock('%s', \$context, \$blocks);\n", $this->getAttribute('name')))
;
}
}

View File

@@ -0,0 +1,21 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Abstract class for all nodes that represents an expression.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
abstract class Twig_Node_Expression extends Twig_Node
{
}

View File

@@ -0,0 +1,41 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Array extends Twig_Node_Expression
{
public function __construct(array $elements, $lineno)
{
parent::__construct($elements, array(), $lineno);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$compiler->raw('array(');
$first = true;
foreach ($this->nodes as $name => $node) {
if (!$first) {
$compiler->raw(', ');
}
$first = false;
$compiler
->repr($name)
->raw(' => ')
->subcompile($node)
;
}
$compiler->raw(')');
}
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_AssignName extends Twig_Node_Expression_Name
{
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$compiler->raw(sprintf('$context[\'%s\']', $this->getAttribute('name')));
}
}

View File

@@ -0,0 +1,40 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
abstract class Twig_Node_Expression_Binary extends Twig_Node_Expression
{
public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno)
{
parent::__construct(array('left' => $left, 'right' => $right), array(), $lineno);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$compiler
->raw('(')
->subcompile($this->getNode('left'))
->raw(' ')
;
$this->operator($compiler);
$compiler
->raw(' ')
->subcompile($this->getNode('right'))
->raw(')')
;
}
abstract public function operator($compiler);
}

View File

@@ -0,0 +1,18 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_Add extends Twig_Node_Expression_Binary
{
public function operator($compiler)
{
return $compiler->raw('+');
}
}

View File

@@ -0,0 +1,18 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_And extends Twig_Node_Expression_Binary
{
public function operator($compiler)
{
return $compiler->raw('&&');
}
}

View File

@@ -0,0 +1,18 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_Concat extends Twig_Node_Expression_Binary
{
public function operator($compiler)
{
return $compiler->raw('.');
}
}

View File

@@ -0,0 +1,18 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_Div extends Twig_Node_Expression_Binary
{
public function operator($compiler)
{
return $compiler->raw('/');
}
}

View File

@@ -0,0 +1,29 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_FloorDiv extends Twig_Node_Expression_Binary
{
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$compiler->raw('floor(');
parent::compile($compiler);
$compiler->raw(')');
}
public function operator($compiler)
{
return $compiler->raw('/');
}
}

View File

@@ -0,0 +1,18 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_Mod extends Twig_Node_Expression_Binary
{
public function operator($compiler)
{
return $compiler->raw('%');
}
}

View File

@@ -0,0 +1,18 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_Mul extends Twig_Node_Expression_Binary
{
public function operator($compiler)
{
return $compiler->raw('*');
}
}

View File

@@ -0,0 +1,18 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_Or extends Twig_Node_Expression_Binary
{
public function operator($compiler)
{
return $compiler->raw('||');
}
}

View File

@@ -0,0 +1,18 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_Sub extends Twig_Node_Expression_Binary
{
public function operator($compiler)
{
return $compiler->raw('-');
}
}

View File

@@ -0,0 +1,61 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Compare extends Twig_Node_Expression
{
public function __construct(Twig_Node_Expression $expr, Twig_NodeInterface $ops, $lineno)
{
parent::__construct(array('expr' => $expr, 'ops' => $ops), array(), $lineno);
}
public function compile($compiler)
{
if ('in' === $this->getNode('ops')->getNode('0')->getAttribute('value')) {
return $this->compileIn($compiler);
}
$this->getNode('expr')->compile($compiler);
$nbOps = count($this->getNode('ops'));
for ($i = 0; $i < $nbOps; $i += 2) {
if ($i > 0) {
$compiler->raw(' && ($tmp'.($i / 2));
}
$compiler->raw(' '.$this->getNode('ops')->getNode($i)->getAttribute('value').' ');
if ($i != $nbOps - 2) {
$compiler
->raw('($tmp'.(($i / 2) + 1).' = ')
->subcompile($this->getNode('ops')->getNode($i + 1))
->raw(')')
;
} else {
$compiler->subcompile($this->getNode('ops')->getNode($i + 1));
}
}
for ($j = 1; $j < $i / 2; $j++) {
$compiler->raw(')');
}
}
protected function compileIn($compiler)
{
$compiler
->raw('twig_in_filter(')
->subcompile($this->getNode('expr'))
->raw(', ')
->subcompile($this->getNode('ops')->getNode(1))
->raw(')')
;
}
}

View File

@@ -0,0 +1,31 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Conditional extends Twig_Node_Expression
{
public function __construct(Twig_Node_Expression $expr1, Twig_Node_Expression $expr2, Twig_Node_Expression $expr3, $lineno)
{
parent::__construct(array('expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3), array(), $lineno);
}
public function compile($compiler)
{
$compiler
->raw('(')
->subcompile($this->getNode('expr1'))
->raw(') ? (')
->subcompile($this->getNode('expr2'))
->raw(') : (')
->subcompile($this->getNode('expr3'))
->raw(')')
;
}
}

View File

@@ -0,0 +1,23 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Constant extends Twig_Node_Expression
{
public function __construct($value, $lineno)
{
parent::__construct(array(), array('value' => $value), $lineno);
}
public function compile($compiler)
{
$compiler->repr($this->getAttribute('value'));
}
}

View File

@@ -0,0 +1,34 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents an extension call node.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Twig_Node_Expression_ExtensionReference extends Twig_Node_Expression
{
public function __construct($name, $lineno, $tag = null)
{
parent::__construct(array(), array('name' => $name), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$compiler->raw(sprintf("\$this->env->getExtension('%s')", $this->getAttribute('name')));
}
}

View File

@@ -0,0 +1,43 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Filter extends Twig_Node_Expression
{
public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filter_name, Twig_NodeInterface $arguments, $lineno, $tag = null)
{
parent::__construct(array('node' => $node, 'filter' => $filter_name, 'arguments' => $arguments), array(), $lineno, $tag);
}
public function compile($compiler)
{
$filterMap = $compiler->getEnvironment()->getFilters();
$name = $this->getNode('filter')->getAttribute('value');
$attrs = $this->getNode('arguments');
if (!isset($filterMap[$name])) {
throw new Twig_Error_Syntax(sprintf('The filter "%s" does not exist', $name), $this->getLine());
} else {
$compiler->raw($filterMap[$name]->compile().($filterMap[$name]->needsEnvironment() ? '($this->env, ' : '('));
}
$this->getNode('node')->compile($compiler);
foreach ($attrs as $node) {
$compiler
->raw(', ')
->subcompile($node)
;
}
$compiler->raw(')');
}
}

View File

@@ -0,0 +1,45 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_GetAttr extends Twig_Node_Expression
{
const TYPE_ANY = 'any';
const TYPE_ARRAY = 'array';
const TYPE_METHOD = 'method';
public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_NodeInterface $arguments, $type, $lineno)
{
parent::__construct(array('node' => $node, 'attribute' => $attribute, 'arguments' => $arguments), array('type' => $type), $lineno);
}
public function compile($compiler)
{
$compiler
->raw('$this->getAttribute(')
->subcompile($this->getNode('node'))
->raw(', ')
->subcompile($this->getNode('attribute'))
->raw(', array(')
;
foreach ($this->getNode('arguments') as $node) {
$compiler
->subcompile($node)
->raw(', ')
;
}
$compiler
->raw('), ')
->repr($this->getAttribute('type'))
->raw(')');
}
}

View File

@@ -0,0 +1,33 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Name extends Twig_Node_Expression
{
public function __construct($name, $lineno)
{
parent::__construct(array(), array('name' => $name), $lineno);
}
public function compile($compiler)
{
if ('_self' === $this->getAttribute('name')) {
$compiler->raw('$this');
} elseif ('_context' === $this->getAttribute('name')) {
$compiler->raw('$context');
} elseif ('_charset' === $this->getAttribute('name')) {
$compiler->raw('$this->getEnvironment()->getCharset()');
} elseif ($compiler->getEnvironment()->isStrictVariables()) {
$compiler->raw(sprintf('$this->getContext($context, \'%s\')', $this->getAttribute('name'), $this->getAttribute('name')));
} else {
$compiler->raw(sprintf('(isset($context[\'%s\']) ? $context[\'%s\'] : null)', $this->getAttribute('name'), $this->getAttribute('name')));
}
}
}

View File

@@ -0,0 +1,60 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2010 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Test extends Twig_Node_Expression
{
public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno)
{
parent::__construct(array('node' => $node, 'arguments' => $arguments), array('name' => $name), $lineno);
}
public function compile($compiler)
{
$testMap = $compiler->getEnvironment()->getTests();
if (!isset($testMap[$this->getAttribute('name')])) {
throw new Twig_Error_Syntax(sprintf('The test "%s" does not exist', $this->getAttribute('name')), $this->getLine());
}
// defined is a special case
if ('defined' === $this->getAttribute('name')) {
if (!$this->getNode('node') instanceof Twig_Node_Expression_Name){
throw new Twig_Error_Syntax('The "defined" test only works with simple variables', $this->getLine());
}
$compiler
->raw($testMap[$this->getAttribute('name')]->compile().'(')
->repr($this->getNode('node')->getAttribute('name'))
->raw(', $context)')
;
return;
}
$compiler
->raw($testMap[$this->getAttribute('name')]->compile().'(')
->subcompile($this->getNode('node'))
;
if (null !== $this->getNode('arguments')) {
$compiler->raw(', ');
$max = count($this->getNode('arguments')) - 1;
foreach ($this->getNode('arguments') as $i => $node) {
$compiler->subcompile($node);
if ($i != $max) {
$compiler->raw(', ');
}
}
}
$compiler->raw(')');
}
}

View File

@@ -0,0 +1,30 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
abstract class Twig_Node_Expression_Unary extends Twig_Node_Expression
{
public function __construct(Twig_NodeInterface $node, $lineno)
{
parent::__construct(array('node' => $node), array(), $lineno);
}
public function compile($compiler)
{
$compiler->raw('(');
$this->operator($compiler);
$compiler
->subcompile($this->getNode('node'))
->raw(')')
;
}
abstract public function operator($compiler);
}

View File

@@ -0,0 +1,18 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Unary_Neg extends Twig_Node_Expression_Unary
{
public function operator($compiler)
{
$compiler->raw('-');
}
}

View File

@@ -0,0 +1,18 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Unary_Not extends Twig_Node_Expression_Unary
{
public function operator($compiler)
{
$compiler->raw('!');
}
}

View File

@@ -0,0 +1,18 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Unary_Pos extends Twig_Node_Expression_Unary
{
public function operator($compiler)
{
$compiler->raw('+');
}
}

124
lib/classes/Twig/Node/For.php Executable file
View File

@@ -0,0 +1,124 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a for node.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Twig_Node_For extends Twig_Node
{
public function __construct(Twig_Node_Expression_AssignName $keyTarget, Twig_Node_Expression_AssignName $valueTarget, Twig_Node_Expression $seq, Twig_NodeInterface $body, Twig_NodeInterface $else = null, $withLoop = false, $lineno, $tag = null)
{
parent::__construct(array('key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body, 'else' => $else), array('with_loop' => $withLoop), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$compiler
->addDebugInfo($this)
// the (array) cast bypasses a PHP 5.2.6 bug
->write('$context[\'_parent\'] = (array) $context;'."\n")
;
if (null !== $this->getNode('else')) {
$compiler->write("\$context['_iterated'] = false;\n");
}
$compiler
->write("\$context['_seq'] = twig_iterator_to_array(")
->subcompile($this->getNode('seq'))
->raw(");\n")
;
if ($this->getAttribute('with_loop')) {
$compiler
->write("\$countable = is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof Countable);\n")
->write("\$length = \$countable ? count(\$context['_seq']) : null;\n")
->write("\$context['loop'] = array(\n")
->write(" 'parent' => \$context['_parent'],\n")
->write(" 'index0' => 0,\n")
->write(" 'index' => 1,\n")
->write(" 'first' => true,\n")
->write(");\n")
->write("if (\$countable) {\n")
->indent()
->write("\$context['loop']['revindex0'] = \$length - 1;\n")
->write("\$context['loop']['revindex'] = \$length;\n")
->write("\$context['loop']['length'] = \$length;\n")
->write("\$context['loop']['last'] = 1 === \$length;\n")
->outdent()
->write("}\n")
;
}
$compiler
->write("foreach (\$context['_seq'] as ")
->subcompile($this->getNode('key_target'))
->raw(" => ")
->subcompile($this->getNode('value_target'))
->raw(") {\n")
->indent()
;
if (null !== $this->getNode('else')) {
$compiler->write("\$context['_iterated'] = true;\n");
}
$compiler->subcompile($this->getNode('body'));
if ($this->getAttribute('with_loop')) {
$compiler
->write("++\$context['loop']['index0'];\n")
->write("++\$context['loop']['index'];\n")
->write("\$context['loop']['first'] = false;\n")
->write("if (\$countable) {\n")
->indent()
->write("--\$context['loop']['revindex0'];\n")
->write("--\$context['loop']['revindex'];\n")
->write("\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];\n")
->outdent()
->write("}\n")
;
}
$compiler
->outdent()
->write("}\n")
;
if (null !== $this->getNode('else')) {
$compiler
->write("if (!\$context['_iterated']) {\n")
->indent()
->subcompile($this->getNode('else'))
->outdent()
->write("}\n")
;
}
$compiler->write('$_parent = $context[\'_parent\'];'."\n");
// remove some "private" loop variables (needed for nested loops)
$compiler->write('unset($context[\'_seq\'], $context[\'_iterated\'], $context[\''.$this->getNode('key_target')->getAttribute('name').'\'], $context[\''.$this->getNode('value_target')->getAttribute('name').'\'], $context[\'_parent\'], $context[\'loop\']);'."\n");
/// keep the values set in the inner context for variables defined in the outer context
$compiler->write('$context = array_merge($_parent, array_intersect_key($context, $_parent));'."\n");
}
}

67
lib/classes/Twig/Node/If.php Executable file
View File

@@ -0,0 +1,67 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents an if node.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Twig_Node_If extends Twig_Node
{
public function __construct(Twig_NodeInterface $tests, Twig_NodeInterface $else = null, $lineno, $tag = null)
{
parent::__construct(array('tests' => $tests, 'else' => $else), array(), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$compiler->addDebugInfo($this);
for ($i = 0; $i < count($this->getNode('tests')); $i += 2) {
if ($i > 0) {
$compiler
->outdent()
->write("} elseif (")
;
} else {
$compiler
->write('if (')
;
}
$compiler
->subcompile($this->getNode('tests')->getNode($i))
->raw(") {\n")
->indent()
->subcompile($this->getNode('tests')->getNode($i + 1))
;
}
if ($this->hasNode('else') && null !== $this->getNode('else')) {
$compiler
->outdent()
->write("} else {\n")
->indent()
->subcompile($this->getNode('else'))
;
}
$compiler
->outdent()
->write("}\n");
}
}

View File

@@ -0,0 +1,51 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents an import node.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Twig_Node_Import extends Twig_Node
{
public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression_AssignName $var, $lineno, $tag = null)
{
parent::__construct(array('expr' => $expr, 'var' => $var), array(), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$compiler
->addDebugInfo($this)
->write('')
->subcompile($this->getNode('var'))
->raw(' = ')
;
if ($this->getNode('expr') instanceof Twig_Node_Expression_Name && '_self' === $this->getNode('expr')->getAttribute('name')) {
$compiler->raw("\$this");
} else {
$compiler
->raw('$this->env->loadTemplate(')
->subcompile($this->getNode('expr'))
->raw(", true)")
;
}
$compiler->raw(";\n");
}
}

View File

@@ -0,0 +1,76 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents an include node.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Twig_Node_Include extends Twig_Node
{
public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $variables = null, $only = false, $lineno, $tag = null)
{
parent::__construct(array('expr' => $expr, 'variables' => $variables), array('only' => (Boolean) $only), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$compiler->addDebugInfo($this);
if ($this->getNode('expr') instanceof Twig_Node_Expression_Constant) {
$compiler
->write("\$this->env->loadTemplate(")
->subcompile($this->getNode('expr'))
->raw(")->display(")
;
} else {
$compiler
->write("\$template = ")
->subcompile($this->getNode('expr'))
->raw(";\n")
->write("if (!\$template")
->raw(" instanceof Twig_Template) {\n")
->indent()
->write("\$template = \$this->env->loadTemplate(\$template);\n")
->outdent()
->write("}\n")
->write('$template->display(')
;
}
if (false === $this->getAttribute('only')) {
if (null === $this->getNode('variables')) {
$compiler->raw('$context');
} else {
$compiler
->raw('array_merge($context, ')
->subcompile($this->getNode('variables'))
->raw(')')
;
}
} else {
if (null === $this->getNode('variables')) {
$compiler->raw('array()');
} else {
$compiler->subcompile($this->getNode('variables'));
}
}
$compiler->raw(");\n");
}
}

62
lib/classes/Twig/Node/Macro.php Executable file
View File

@@ -0,0 +1,62 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a macro node.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Twig_Node_Macro extends Twig_Node
{
public function __construct($name, Twig_NodeInterface $body, Twig_NodeInterface $arguments, $lineno, $tag = null)
{
parent::__construct(array('body' => $body, 'arguments' => $arguments), array('name' => $name), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$arguments = array();
foreach ($this->getNode('arguments') as $argument) {
$arguments[] = '$'.$argument->getAttribute('name').' = null';
}
$compiler
->addDebugInfo($this)
->write(sprintf("public function get%s(%s)\n", $this->getAttribute('name'), implode(', ', $arguments)), "{\n")
->indent()
->write("\$context = array(\n")
->indent()
;
foreach ($this->getNode('arguments') as $argument) {
$compiler
->write('')
->string($argument->getAttribute('name'))
->raw(' => $'.$argument->getAttribute('name'))
->raw(",\n")
;
}
$compiler
->outdent()
->write(");\n\n")
->subcompile($this->getNode('body'))
->outdent()
->write("}\n\n")
;
}
}

188
lib/classes/Twig/Node/Module.php Executable file
View File

@@ -0,0 +1,188 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a module node.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Twig_Node_Module extends Twig_Node
{
public function __construct(Twig_NodeInterface $body, Twig_Node_Expression $parent = null, Twig_NodeInterface $blocks, Twig_NodeInterface $macros, $filename)
{
parent::__construct(array('parent' => $parent, 'body' => $body, 'blocks' => $blocks, 'macros' => $macros), array('filename' => $filename), 1);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$this->compileTemplate($compiler);
}
protected function compileTemplate($compiler)
{
$this->compileClassHeader($compiler);
if (count($this->getNode('blocks'))) {
$this->compileConstructor($compiler);
}
$this->compileGetParent($compiler);
$this->compileDisplayHeader($compiler);
$this->compileDisplayBody($compiler);
$this->compileDisplayFooter($compiler);
$compiler->subcompile($this->getNode('blocks'));
$this->compileMacros($compiler);
$this->compileClassFooter($compiler);
}
protected function compileGetParent($compiler)
{
if (null === $this->getNode('parent')) {
return;
}
$compiler
->write("public function getParent(array \$context)\n", "{\n")
->indent()
->write("if (null === \$this->parent) {\n")
->indent();
;
if ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
$compiler
->write("\$this->parent = \$this->env->loadTemplate(")
->subcompile($this->getNode('parent'))
->raw(");\n")
;
} else {
$compiler
->write("\$this->parent = ")
->subcompile($this->getNode('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->getNode('parent')) {
// remove all but import nodes
foreach ($this->getNode('body') as $node) {
if ($node instanceof Twig_Node_Import) {
$compiler->subcompile($node);
}
}
$compiler
->write("\$this->getParent(\$context)->display(\$context, array_merge(\$this->blocks, \$blocks));\n")
;
} else {
$compiler->subcompile($this->getNode('body'));
}
}
protected function compileClassHeader($compiler)
{
$compiler
->write("<?php\n\n")
// if the filename contains */, add a blank to avoid a PHP parse error
->write("/* ".str_replace('*/', '* /', $this->getAttribute('filename'))." */\n")
->write('class '.$compiler->getEnvironment()->getTemplateClass($this->getAttribute('filename')))
->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass()))
->write("{\n")
->indent()
;
if (null !== $this->getNode('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->getNode('blocks') as $name => $node) {
$compiler
->write(sprintf("'%s' => array(\$this, 'block_%s'),\n", $name, $name))
;
}
$compiler
->outdent()
->write(");\n")
->outdent()
->write("}\n\n");
;
}
protected function compileDisplayHeader($compiler)
{
$compiler
->write("public function display(array \$context, array \$blocks = array())\n", "{\n")
->indent()
;
}
protected function compileDisplayFooter($compiler)
{
$compiler
->outdent()
->write("}\n\n")
;
}
protected function compileClassFooter($compiler)
{
$compiler
->outdent()
->write("}\n")
;
}
protected function compileMacros($compiler)
{
$compiler->subcompile($this->getNode('macros'));
}
}

View File

@@ -0,0 +1,40 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a parent node.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Twig_Node_Parent extends Twig_Node
{
public function __construct($name, $lineno, $tag = null)
{
parent::__construct(array(), array('name' => $name), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$compiler
->addDebugInfo($this)
->write("\$this->getParentBlock(")
->string($this->getAttribute('name'))
->raw(", \$context, \$blocks);\n")
;
}
}

40
lib/classes/Twig/Node/Print.php Executable file
View File

@@ -0,0 +1,40 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a node that outputs an expression.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Twig_Node_Print extends Twig_Node
{
public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null)
{
parent::__construct(array('expr' => $expr), array(), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$compiler
->addDebugInfo($this)
->write('echo ')
->subcompile($this->getNode('expr'))
->raw(";\n")
;
}
}

View File

@@ -0,0 +1,48 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2010 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a sandbox node.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Twig_Node_Sandbox extends Twig_Node
{
public function __construct(Twig_NodeInterface $body, $lineno, $tag = null)
{
parent::__construct(array('body' => $body), array(), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$compiler
->addDebugInfo($this)
->write("\$sandbox = \$this->env->getExtension('sandbox');\n")
->write("if (!\$alreadySandboxed = \$sandbox->isSandboxed()) {\n")
->indent()
->write("\$sandbox->enableSandbox();\n")
->outdent()
->write("}\n")
->subcompile($this->getNode('body'))
->write("if (!\$alreadySandboxed) {\n")
->indent()
->write("\$sandbox->disableSandbox();\n")
->outdent()
->write("}\n")
;
}
}

View File

@@ -0,0 +1,68 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a module node.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Twig_Node_SandboxedModule extends Twig_Node_Module
{
protected $usedFilters;
protected $usedTags;
public function __construct(Twig_Node_Module $node, array $usedFilters, array $usedTags)
{
parent::__construct($node->getNode('body'), $node->getNode('parent'), $node->getNode('blocks'), $node->getNode('macros'), $node->getAttribute('filename'), $node->getLine(), $node->getNodeTag());
$this->usedFilters = $usedFilters;
$this->usedTags = $usedTags;
}
protected function compileDisplayBody($compiler)
{
if (null === $this->getNode('parent')) {
$compiler->write("\$this->checkSecurity();\n");
}
parent::compileDisplayBody($compiler);
}
protected function compileDisplayFooter($compiler)
{
parent::compileDisplayFooter($compiler);
$compiler
->write("protected function checkSecurity() {\n")
->indent()
->write("\$this->env->getExtension('sandbox')->checkSecurity(\n")
->indent()
->write(!$this->usedTags ? "array(),\n" : "array('".implode('\', \'', $this->usedTags)."'),\n")
->write(!$this->usedFilters ? "array()\n" : "array('".implode('\', \'', $this->usedFilters)."')\n")
->outdent()
->write(");\n")
;
if (null !== $this->getNode('parent')) {
$compiler
->raw("\n")
->write("\$this->parent->checkSecurity();\n")
;
}
$compiler
->outdent()
->write("}\n\n")
;
}
}

View File

@@ -0,0 +1,52 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2010 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Twig_Node_SandboxedPrint adds a check for the __toString() method
* when the variable is an object and the sandbox is activated.
*
* When there is a simple Print statement, like {{ article }},
* and if the sandbox is enabled, we need to check that the __toString()
* method is allowed if 'article' is an object.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Twig_Node_SandboxedPrint extends Twig_Node_Print
{
public function __construct(Twig_Node_Print $node)
{
parent::__construct($node->getNode('expr'), $node->getLine(), $node->getNodeTag());
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$compiler
->addDebugInfo($this)
->write('if ($this->env->hasExtension(\'sandbox\') && is_object(')
->subcompile($this->getNode('expr'))
->raw(')) {'."\n")
->indent()
->write('$this->env->getExtension(\'sandbox\')->checkMethodAllowed(')
->subcompile($this->getNode('expr'))
->raw(', \'__toString\');'."\n")
->outdent()
->write('}'."\n")
;
parent::compile($compiler);
}
}

79
lib/classes/Twig/Node/Set.php Executable file
View File

@@ -0,0 +1,79 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2010 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a set node.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Twig_Node_Set extends Twig_Node
{
public function __construct($capture, Twig_NodeInterface $names, Twig_NodeInterface $values, $lineno, $tag = null)
{
parent::__construct(array('names' => $names, 'values' => $values), array('capture' => $capture), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$compiler->addDebugInfo($this);
if (count($this->getNode('names')) > 1) {
$compiler->write('list(');
foreach ($this->getNode('names') as $idx => $node) {
if ($idx) {
$compiler->raw(', ');
}
$compiler->subcompile($node);
}
$compiler->raw(')');
} else {
if ($this->getAttribute('capture')) {
$compiler
->write("ob_start();\n")
->subcompile($this->getNode('values'))
;
}
$compiler->subcompile($this->getNode('names'), false);
if ($this->getAttribute('capture')) {
$compiler->raw(" = ob_get_clean()");
}
}
if (!$this->getAttribute('capture')) {
$compiler->raw(' = ');
if (count($this->getNode('names')) > 1) {
$compiler->write('array(');
foreach ($this->getNode('values') as $idx => $value) {
if ($idx) {
$compiler->raw(', ');
}
$compiler->subcompile($value);
}
$compiler->raw(')');
} else {
$compiler->subcompile($this->getNode('values'));
}
}
$compiler->raw(";\n");
}
}

View File

@@ -0,0 +1,41 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2010 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a spaceless node.
*
* It removes spaces between HTML tags.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Twig_Node_Spaceless extends Twig_Node
{
public function __construct(Twig_NodeInterface $body, $lineno, $tag = 'spaceless')
{
parent::__construct(array('body' => $body), array(), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$compiler
->addDebugInfo($this)
->write("ob_start();\n")
->subcompile($this->getNode('body'))
->write("echo trim(preg_replace('/>\s+</', '><', ob_get_clean()));\n")
;
}
}

40
lib/classes/Twig/Node/Text.php Executable file
View File

@@ -0,0 +1,40 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a text node.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Twig_Node_Text extends Twig_Node
{
public function __construct($data, $lineno)
{
parent::__construct(array(), array('data' => $data), $lineno);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$compiler
->addDebugInfo($this)
->write('echo ')
->string($this->getAttribute('data'))
->raw(";\n")
;
}
}

124
lib/classes/Twig/Node/Trans.php Executable file
View File

@@ -0,0 +1,124 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2010 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a trans node.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Twig_Node_Trans extends Twig_Node
{
public function __construct(Twig_NodeInterface $body, Twig_NodeInterface $plural = null, Twig_Node_Expression $count = null, $lineno, $tag = null)
{
parent::__construct(array('count' => $count, 'body' => $body, 'plural' => $plural), array(), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile($compiler)
{
$compiler->addDebugInfo($this);
list($msg, $vars) = $this->compileString($this->getNode('body'));
if (null !== $this->getNode('plural')) {
list($msg1, $vars1) = $this->compileString($this->getNode('plural'));
$vars = array_merge($vars, $vars1);
}
$function = null === $this->getNode('plural') ? 'gettext' : 'ngettext';
if ($vars) {
$compiler
->write('echo strtr('.$function.'(')
->subcompile($msg)
;
if (null !== $this->getNode('plural')) {
$compiler
->raw(', ')
->subcompile($msg1)
->raw(', abs(')
->subcompile($this->getNode('count'))
->raw(')')
;
}
$compiler->raw('), array(');
foreach ($vars as $var) {
if ('count' === $var->getAttribute('name')) {
$compiler
->string('%count%')
->raw(' => abs(')
->subcompile($this->getNode('count'))
->raw('), ')
;
} else {
$compiler
->string('%'.$var->getAttribute('name').'%')
->raw(' => ')
->subcompile($var)
->raw(', ')
;
}
}
$compiler->raw("));\n");
} else {
$compiler
->write('echo '.$function.'(')
->subcompile($msg)
;
if (null !== $this->getNode('plural')) {
$compiler
->raw(', ')
->subcompile($msg1)
->raw(', abs(')
->subcompile($this->getNode('count'))
->raw(')')
;
}
$compiler->raw(');');
}
}
protected function compileString(Twig_NodeInterface $body)
{
if ($body instanceof Twig_Node_Expression_Name || $body instanceof Twig_Node_Expression_Constant) {
return array($body, array());
}
$msg = '';
$vars = array();
foreach ($body as $node) {
if ($node instanceof Twig_Node_Print) {
$n = $node->getNode('expr');
while ($n instanceof Twig_Node_Expression_Filter) {
$n = $n->getNode('node');
}
$msg .= sprintf('%%%s%%', $n->getAttribute('name'));
$vars[] = new Twig_Node_Expression_Name($n->getAttribute('name'), $n->getLine());
} else {
$msg .= $node->getAttribute('data');
}
}
return array(new Twig_Node(array(new Twig_Node_Expression_Constant(trim($msg), $node->getLine()))), $vars);
}
}