Module.php

File

drupal/core/vendor/twig/twig/lib/Twig/Node/Module.php
View source
<?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@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,
    ), 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 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) {
      $this
        ->compileConstructor($compiler);
    }
    $this
      ->compileGetParent($compiler);
    $this
      ->compileDisplayHeader($compiler);
    $this
      ->compileDisplayBody($compiler);
    $this
      ->compileDisplayFooter($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 === $this
      ->getNode('parent')) {
      return;
    }
    $compiler
      ->write("protected function doGetParent(array \$context)\n", "{\n")
      ->indent()
      ->write("return ");
    if ($this
      ->getNode('parent') instanceof Twig_Node_Expression_Constant) {
      $compiler
        ->subcompile($this
        ->getNode('parent'));
    }
    else {
      $compiler
        ->raw("\$this->env->resolveTemplate(")
        ->subcompile($this
        ->getNode('parent'))
        ->raw(")");
    }
    $compiler
      ->raw(";\n")
      ->outdent()
      ->write("}\n\n");
  }
  protected function compileDisplayBody(Twig_Compiler $compiler) {
    $compiler
      ->subcompile($this
      ->getNode('body'));
    if (null !== $this
      ->getNode('parent')) {
      if ($this
        ->getNode('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");
    }
  }
  protected function compileClassHeader(Twig_Compiler $compiler) {
    $compiler
      ->write("\n\n")
      ->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()
      ->write("parent::__construct(\$env);\n\n");

    // parent
    if (null === $this
      ->getNode('parent')) {
      $compiler
        ->write("\$this->parent = false;\n\n");
    }
    elseif ($this
      ->getNode('parent') instanceof Twig_Node_Expression_Constant) {
      $compiler
        ->write("\$this->parent = \$this->env->loadTemplate(")
        ->subcompile($this
        ->getNode('parent'))
        ->raw(");\n\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("\$_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()
      ->write("}\n\n");
  }
  protected function compileDisplayHeader(Twig_Compiler $compiler) {
    $compiler
      ->write("protected function doDisplay(array \$context, array \$blocks = array())\n", "{\n")
      ->indent();
  }
  protected function compileDisplayFooter(Twig_Compiler $compiler) {
    $compiler
      ->outdent()
      ->write("}\n\n");
  }
  protected function compileClassFooter(Twig_Compiler $compiler) {
    $compiler
      ->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->env->loadTemplate(", $var))
        ->subcompile($node)
        ->raw(");\n");
    }
    else {
      $compiler
        ->write(sprintf("%s = ", $var))
        ->subcompile($node)
        ->raw(";\n")
        ->write(sprintf("if (!%s", $var))
        ->raw(" instanceof Twig_Template) {\n")
        ->indent()
        ->write(sprintf("%s = \$this->env->loadTemplate(%s);\n", $var, $var))
        ->outdent()
        ->write("}\n");
    }
  }

}

Classes

Namesort descending Description
Twig_Node_Module Represents a module node.