Start working

Modified some paths to be more generic and not require rewrite.  Some
instances of phase names have been changed, others are still in process.
This commit is contained in:
mattbk
2015-10-28 22:04:20 -05:00
parent eda91ff492
commit abadd5bc38
192 changed files with 16085 additions and 7 deletions

408
Twig/Node/Module.php Normal file
View File

@ -0,0 +1,408 @@
<?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.
*
* Consider this class as being final. If you need to customize the behavior of
* the generated class, consider adding nodes to the following nodes: display_start,
* display_end, constructor_start, constructor_end, and class_end.
*
* @author Fabien Potencier <fabien@symfony.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, Twig_NodeInterface $traits, $embeddedTemplates, $filename)
{
// embedded templates are set as attributes so that they are only visited once by the visitors
parent::__construct(array(
'parent' => $parent,
'body' => $body,
'blocks' => $blocks,
'macros' => $macros,
'traits' => $traits,
'display_start' => new Twig_Node(),
'display_end' => new Twig_Node(),
'constructor_start' => new Twig_Node(),
'constructor_end' => new Twig_Node(),
'class_end' => new Twig_Node(),
), array(
'filename' => $filename,
'index' => null,
'embedded_templates' => $embeddedTemplates,
), 1);
}
public function setIndex($index)
{
$this->setAttribute('index', $index);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
$this->compileTemplate($compiler);
foreach ($this->getAttribute('embedded_templates') as $template) {
$compiler->subcompile($template);
}
}
protected function compileTemplate(Twig_Compiler $compiler)
{
if (!$this->getAttribute('index')) {
$compiler->write('<?php');
}
$this->compileClassHeader($compiler);
if (
count($this->getNode('blocks'))
|| count($this->getNode('traits'))
|| null === $this->getNode('parent')
|| $this->getNode('parent') instanceof Twig_Node_Expression_Constant
|| count($this->getNode('constructor_start'))
|| count($this->getNode('constructor_end'))
) {
$this->compileConstructor($compiler);
}
$this->compileGetParent($compiler);
$this->compileDisplay($compiler);
$compiler->subcompile($this->getNode('blocks'));
$this->compileMacros($compiler);
$this->compileGetTemplateName($compiler);
$this->compileIsTraitable($compiler);
$this->compileDebugInfo($compiler);
$this->compileClassFooter($compiler);
}
protected function compileGetParent(Twig_Compiler $compiler)
{
if (null === $parent = $this->getNode('parent')) {
return;
}
$compiler
->write("protected function doGetParent(array \$context)\n", "{\n")
->indent()
->addDebugInfo($parent)
->write('return ')
;
if ($parent instanceof Twig_Node_Expression_Constant) {
$compiler->subcompile($parent);
} else {
$compiler
->raw('$this->loadTemplate(')
->subcompile($parent)
->raw(', ')
->repr($compiler->getFilename())
->raw(', ')
->repr($this->getNode('parent')->getLine())
->raw(')')
;
}
$compiler
->raw(";\n")
->outdent()
->write("}\n\n")
;
}
protected function compileClassHeader(Twig_Compiler $compiler)
{
$compiler
->write("\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'), $this->getAttribute('index')))
->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass()))
->write("{\n")
->indent()
;
}
protected function compileConstructor(Twig_Compiler $compiler)
{
$compiler
->write("public function __construct(Twig_Environment \$env)\n", "{\n")
->indent()
->subcompile($this->getNode('constructor_start'))
->write("parent::__construct(\$env);\n\n")
;
// parent
if (null === $parent = $this->getNode('parent')) {
$compiler->write("\$this->parent = false;\n\n");
} elseif ($parent instanceof Twig_Node_Expression_Constant) {
$compiler
->addDebugInfo($parent)
->write('$this->parent = $this->loadTemplate(')
->subcompile($parent)
->raw(', ')
->repr($compiler->getFilename())
->raw(', ')
->repr($this->getNode('parent')->getLine())
->raw(");\n")
;
}
$countTraits = count($this->getNode('traits'));
if ($countTraits) {
// traits
foreach ($this->getNode('traits') as $i => $trait) {
$this->compileLoadTemplate($compiler, $trait->getNode('template'), sprintf('$_trait_%s', $i));
$compiler
->addDebugInfo($trait->getNode('template'))
->write(sprintf("if (!\$_trait_%s->isTraitable()) {\n", $i))
->indent()
->write("throw new Twig_Error_Runtime('Template \"'.")
->subcompile($trait->getNode('template'))
->raw(".'\" cannot be used as a trait.');\n")
->outdent()
->write("}\n")
->write(sprintf("\$_trait_%s_blocks = \$_trait_%s->getBlocks();\n\n", $i, $i))
;
foreach ($trait->getNode('targets') as $key => $value) {
$compiler
->write(sprintf('if (!isset($_trait_%s_blocks[', $i))
->string($key)
->raw("])) {\n")
->indent()
->write("throw new Twig_Error_Runtime(sprintf('Block ")
->string($key)
->raw(' is not defined in trait ')
->subcompile($trait->getNode('template'))
->raw(".'));\n")
->outdent()
->write("}\n\n")
->write(sprintf('$_trait_%s_blocks[', $i))
->subcompile($value)
->raw(sprintf('] = $_trait_%s_blocks[', $i))
->string($key)
->raw(sprintf(']; unset($_trait_%s_blocks[', $i))
->string($key)
->raw("]);\n\n")
;
}
}
if ($countTraits > 1) {
$compiler
->write("\$this->traits = array_merge(\n")
->indent()
;
for ($i = 0; $i < $countTraits; ++$i) {
$compiler
->write(sprintf('$_trait_%s_blocks'.($i == $countTraits - 1 ? '' : ',')."\n", $i))
;
}
$compiler
->outdent()
->write(");\n\n")
;
} else {
$compiler
->write("\$this->traits = \$_trait_0_blocks;\n\n")
;
}
$compiler
->write("\$this->blocks = array_merge(\n")
->indent()
->write("\$this->traits,\n")
->write("array(\n")
;
} else {
$compiler
->write("\$this->blocks = array(\n")
;
}
// blocks
$compiler
->indent()
;
foreach ($this->getNode('blocks') as $name => $node) {
$compiler
->write(sprintf("'%s' => array(\$this, 'block_%s'),\n", $name, $name))
;
}
if ($countTraits) {
$compiler
->outdent()
->write(")\n")
;
}
$compiler
->outdent()
->write(");\n")
->outdent()
->subcompile($this->getNode('constructor_end'))
->write("}\n\n")
;
}
protected function compileDisplay(Twig_Compiler $compiler)
{
$compiler
->write("protected function doDisplay(array \$context, array \$blocks = array())\n", "{\n")
->indent()
->subcompile($this->getNode('display_start'))
->subcompile($this->getNode('body'))
;
if (null !== $parent = $this->getNode('parent')) {
$compiler->addDebugInfo($parent);
if ($parent instanceof Twig_Node_Expression_Constant) {
$compiler->write('$this->parent');
} else {
$compiler->write('$this->getParent($context)');
}
$compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n");
}
$compiler
->subcompile($this->getNode('display_end'))
->outdent()
->write("}\n\n")
;
}
protected function compileClassFooter(Twig_Compiler $compiler)
{
$compiler
->subcompile($this->getNode('class_end'))
->outdent()
->write("}\n")
;
}
protected function compileMacros(Twig_Compiler $compiler)
{
$compiler->subcompile($this->getNode('macros'));
}
protected function compileGetTemplateName(Twig_Compiler $compiler)
{
$compiler
->write("public function getTemplateName()\n", "{\n")
->indent()
->write('return ')
->repr($this->getAttribute('filename'))
->raw(";\n")
->outdent()
->write("}\n\n")
;
}
protected function compileIsTraitable(Twig_Compiler $compiler)
{
// A template can be used as a trait if:
// * it has no parent
// * it has no macros
// * it has no body
//
// Put another way, a template can be used as a trait if it
// only contains blocks and use statements.
$traitable = null === $this->getNode('parent') && 0 === count($this->getNode('macros'));
if ($traitable) {
if ($this->getNode('body') instanceof Twig_Node_Body) {
$nodes = $this->getNode('body')->getNode(0);
} else {
$nodes = $this->getNode('body');
}
if (!count($nodes)) {
$nodes = new Twig_Node(array($nodes));
}
foreach ($nodes as $node) {
if (!count($node)) {
continue;
}
if ($node instanceof Twig_Node_Text && ctype_space($node->getAttribute('data'))) {
continue;
}
if ($node instanceof Twig_Node_BlockReference) {
continue;
}
$traitable = false;
break;
}
}
if ($traitable) {
return;
}
$compiler
->write("public function isTraitable()\n", "{\n")
->indent()
->write(sprintf("return %s;\n", $traitable ? 'true' : 'false'))
->outdent()
->write("}\n\n")
;
}
protected function compileDebugInfo(Twig_Compiler $compiler)
{
$compiler
->write("public function getDebugInfo()\n", "{\n")
->indent()
->write(sprintf("return %s;\n", str_replace("\n", '', var_export(array_reverse($compiler->getDebugInfo(), true), true))))
->outdent()
->write("}\n")
;
}
protected function compileLoadTemplate(Twig_Compiler $compiler, $node, $var)
{
if ($node instanceof Twig_Node_Expression_Constant) {
$compiler
->write(sprintf('%s = $this->loadTemplate(', $var))
->subcompile($node)
->raw(', ')
->repr($compiler->getFilename())
->raw(', ')
->repr($node->getLine())
->raw(");\n")
;
} else {
throw new LogicException('Trait templates can only be constant nodes');
}
}
}