[ Index ]

PHP Cross Reference of phpBB-3.3.2-deutsch

title

Body

[close]

/vendor/twig/twig/src/Node/ -> ModuleNode.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of Twig.
   5   *
   6   * (c) Fabien Potencier
   7   * (c) Armin Ronacher
   8   *
   9   * For the full copyright and license information, please view the LICENSE
  10   * file that was distributed with this source code.
  11   */
  12  
  13  namespace Twig\Node;
  14  
  15  use Twig\Compiler;
  16  use Twig\Node\Expression\AbstractExpression;
  17  use Twig\Node\Expression\ConstantExpression;
  18  use Twig\Source;
  19  
  20  /**
  21   * Represents a module node.
  22   *
  23   * Consider this class as being final. If you need to customize the behavior of
  24   * the generated class, consider adding nodes to the following nodes: display_start,
  25   * display_end, constructor_start, constructor_end, and class_end.
  26   *
  27   * @author Fabien Potencier <fabien@symfony.com>
  28   *
  29   * @final since Twig 2.4.0
  30   */
  31  class ModuleNode extends Node
  32  {
  33      public function __construct(Node $body, ?AbstractExpression $parent, Node $blocks, Node $macros, Node $traits, $embeddedTemplates, Source $source)
  34      {
  35          if (__CLASS__ !== static::class) {
  36              @trigger_error('Overriding '.__CLASS__.' is deprecated since Twig 2.4.0 and the class will be final in 3.0.', E_USER_DEPRECATED);
  37          }
  38  
  39          $nodes = [
  40              'body' => $body,
  41              'blocks' => $blocks,
  42              'macros' => $macros,
  43              'traits' => $traits,
  44              'display_start' => new Node(),
  45              'display_end' => new Node(),
  46              'constructor_start' => new Node(),
  47              'constructor_end' => new Node(),
  48              'class_end' => new Node(),
  49          ];
  50          if (null !== $parent) {
  51              $nodes['parent'] = $parent;
  52          }
  53  
  54          // embedded templates are set as attributes so that they are only visited once by the visitors
  55          parent::__construct($nodes, [
  56              'index' => null,
  57              'embedded_templates' => $embeddedTemplates,
  58          ], 1);
  59  
  60          // populate the template name of all node children
  61          $this->setSourceContext($source);
  62      }
  63  
  64      public function setIndex($index)
  65      {
  66          $this->setAttribute('index', $index);
  67      }
  68  
  69      public function compile(Compiler $compiler)
  70      {
  71          $this->compileTemplate($compiler);
  72  
  73          foreach ($this->getAttribute('embedded_templates') as $template) {
  74              $compiler->subcompile($template);
  75          }
  76      }
  77  
  78      protected function compileTemplate(Compiler $compiler)
  79      {
  80          if (!$this->getAttribute('index')) {
  81              $compiler->write('<?php');
  82          }
  83  
  84          $this->compileClassHeader($compiler);
  85  
  86          $this->compileConstructor($compiler);
  87  
  88          $this->compileGetParent($compiler);
  89  
  90          $this->compileDisplay($compiler);
  91  
  92          $compiler->subcompile($this->getNode('blocks'));
  93  
  94          $this->compileMacros($compiler);
  95  
  96          $this->compileGetTemplateName($compiler);
  97  
  98          $this->compileIsTraitable($compiler);
  99  
 100          $this->compileDebugInfo($compiler);
 101  
 102          $this->compileGetSourceContext($compiler);
 103  
 104          $this->compileClassFooter($compiler);
 105      }
 106  
 107      protected function compileGetParent(Compiler $compiler)
 108      {
 109          if (!$this->hasNode('parent')) {
 110              return;
 111          }
 112          $parent = $this->getNode('parent');
 113  
 114          $compiler
 115              ->write("protected function doGetParent(array \$context)\n", "{\n")
 116              ->indent()
 117              ->addDebugInfo($parent)
 118              ->write('return ')
 119          ;
 120  
 121          if ($parent instanceof ConstantExpression) {
 122              $compiler->subcompile($parent);
 123          } else {
 124              $compiler
 125                  ->raw('$this->loadTemplate(')
 126                  ->subcompile($parent)
 127                  ->raw(', ')
 128                  ->repr($this->getSourceContext()->getName())
 129                  ->raw(', ')
 130                  ->repr($parent->getTemplateLine())
 131                  ->raw(')')
 132              ;
 133          }
 134  
 135          $compiler
 136              ->raw(";\n")
 137              ->outdent()
 138              ->write("}\n\n")
 139          ;
 140      }
 141  
 142      protected function compileClassHeader(Compiler $compiler)
 143      {
 144          $compiler
 145              ->write("\n\n")
 146          ;
 147          if (!$this->getAttribute('index')) {
 148              $compiler
 149                  ->write("use Twig\Environment;\n")
 150                  ->write("use Twig\Error\LoaderError;\n")
 151                  ->write("use Twig\Error\RuntimeError;\n")
 152                  ->write("use Twig\Extension\SandboxExtension;\n")
 153                  ->write("use Twig\Markup;\n")
 154                  ->write("use Twig\Sandbox\SecurityError;\n")
 155                  ->write("use Twig\Sandbox\SecurityNotAllowedTagError;\n")
 156                  ->write("use Twig\Sandbox\SecurityNotAllowedFilterError;\n")
 157                  ->write("use Twig\Sandbox\SecurityNotAllowedFunctionError;\n")
 158                  ->write("use Twig\Source;\n")
 159                  ->write("use Twig\Template;\n\n")
 160              ;
 161          }
 162          $compiler
 163              // if the template name contains */, add a blank to avoid a PHP parse error
 164              ->write('/* '.str_replace('*/', '* /', $this->getSourceContext()->getName())." */\n")
 165              ->write('class '.$compiler->getEnvironment()->getTemplateClass($this->getSourceContext()->getName(), $this->getAttribute('index')))
 166              ->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass(false)))
 167              ->write("{\n")
 168              ->indent()
 169              ->write("private \$source;\n")
 170              ->write("private \$macros = [];\n\n")
 171          ;
 172      }
 173  
 174      protected function compileConstructor(Compiler $compiler)
 175      {
 176          $compiler
 177              ->write("public function __construct(Environment \$env)\n", "{\n")
 178              ->indent()
 179              ->subcompile($this->getNode('constructor_start'))
 180              ->write("parent::__construct(\$env);\n\n")
 181              ->write("\$this->source = \$this->getSourceContext();\n\n")
 182          ;
 183  
 184          // parent
 185          if (!$this->hasNode('parent')) {
 186              $compiler->write("\$this->parent = false;\n\n");
 187          }
 188  
 189          $countTraits = \count($this->getNode('traits'));
 190          if ($countTraits) {
 191              // traits
 192              foreach ($this->getNode('traits') as $i => $trait) {
 193                  $node = $trait->getNode('template');
 194  
 195                  $compiler
 196                      ->addDebugInfo($node)
 197                      ->write(sprintf('$_trait_%s = $this->loadTemplate(', $i))
 198                      ->subcompile($node)
 199                      ->raw(', ')
 200                      ->repr($node->getTemplateName())
 201                      ->raw(', ')
 202                      ->repr($node->getTemplateLine())
 203                      ->raw(");\n")
 204                      ->write(sprintf("if (!\$_trait_%s->isTraitable()) {\n", $i))
 205                      ->indent()
 206                      ->write("throw new RuntimeError('Template \"'.")
 207                      ->subcompile($trait->getNode('template'))
 208                      ->raw(".'\" cannot be used as a trait.', ")
 209                      ->repr($node->getTemplateLine())
 210                      ->raw(", \$this->source);\n")
 211                      ->outdent()
 212                      ->write("}\n")
 213                      ->write(sprintf("\$_trait_%s_blocks = \$_trait_%s->getBlocks();\n\n", $i, $i))
 214                  ;
 215  
 216                  foreach ($trait->getNode('targets') as $key => $value) {
 217                      $compiler
 218                          ->write(sprintf('if (!isset($_trait_%s_blocks[', $i))
 219                          ->string($key)
 220                          ->raw("])) {\n")
 221                          ->indent()
 222                          ->write("throw new RuntimeError('Block ")
 223                          ->string($key)
 224                          ->raw(' is not defined in trait ')
 225                          ->subcompile($trait->getNode('template'))
 226                          ->raw(".', ")
 227                          ->repr($node->getTemplateLine())
 228                          ->raw(", \$this->source);\n")
 229                          ->outdent()
 230                          ->write("}\n\n")
 231  
 232                          ->write(sprintf('$_trait_%s_blocks[', $i))
 233                          ->subcompile($value)
 234                          ->raw(sprintf('] = $_trait_%s_blocks[', $i))
 235                          ->string($key)
 236                          ->raw(sprintf(']; unset($_trait_%s_blocks[', $i))
 237                          ->string($key)
 238                          ->raw("]);\n\n")
 239                      ;
 240                  }
 241              }
 242  
 243              if ($countTraits > 1) {
 244                  $compiler
 245                      ->write("\$this->traits = array_merge(\n")
 246                      ->indent()
 247                  ;
 248  
 249                  for ($i = 0; $i < $countTraits; ++$i) {
 250                      $compiler
 251                          ->write(sprintf('$_trait_%s_blocks'.($i == $countTraits - 1 ? '' : ',')."\n", $i))
 252                      ;
 253                  }
 254  
 255                  $compiler
 256                      ->outdent()
 257                      ->write(");\n\n")
 258                  ;
 259              } else {
 260                  $compiler
 261                      ->write("\$this->traits = \$_trait_0_blocks;\n\n")
 262                  ;
 263              }
 264  
 265              $compiler
 266                  ->write("\$this->blocks = array_merge(\n")
 267                  ->indent()
 268                  ->write("\$this->traits,\n")
 269                  ->write("[\n")
 270              ;
 271          } else {
 272              $compiler
 273                  ->write("\$this->blocks = [\n")
 274              ;
 275          }
 276  
 277          // blocks
 278          $compiler
 279              ->indent()
 280          ;
 281  
 282          foreach ($this->getNode('blocks') as $name => $node) {
 283              $compiler
 284                  ->write(sprintf("'%s' => [\$this, 'block_%s'],\n", $name, $name))
 285              ;
 286          }
 287  
 288          if ($countTraits) {
 289              $compiler
 290                  ->outdent()
 291                  ->write("]\n")
 292                  ->outdent()
 293                  ->write(");\n")
 294              ;
 295          } else {
 296              $compiler
 297                  ->outdent()
 298                  ->write("];\n")
 299              ;
 300          }
 301  
 302          $compiler
 303              ->subcompile($this->getNode('constructor_end'))
 304              ->outdent()
 305              ->write("}\n\n")
 306          ;
 307      }
 308  
 309      protected function compileDisplay(Compiler $compiler)
 310      {
 311          $compiler
 312              ->write("protected function doDisplay(array \$context, array \$blocks = [])\n", "{\n")
 313              ->indent()
 314              ->write("\$macros = \$this->macros;\n")
 315              ->subcompile($this->getNode('display_start'))
 316              ->subcompile($this->getNode('body'))
 317          ;
 318  
 319          if ($this->hasNode('parent')) {
 320              $parent = $this->getNode('parent');
 321  
 322              $compiler->addDebugInfo($parent);
 323              if ($parent instanceof ConstantExpression) {
 324                  $compiler
 325                      ->write('$this->parent = $this->loadTemplate(')
 326                      ->subcompile($parent)
 327                      ->raw(', ')
 328                      ->repr($this->getSourceContext()->getName())
 329                      ->raw(', ')
 330                      ->repr($parent->getTemplateLine())
 331                      ->raw(");\n")
 332                  ;
 333                  $compiler->write('$this->parent');
 334              } else {
 335                  $compiler->write('$this->getParent($context)');
 336              }
 337              $compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n");
 338          }
 339  
 340          $compiler
 341              ->subcompile($this->getNode('display_end'))
 342              ->outdent()
 343              ->write("}\n\n")
 344          ;
 345      }
 346  
 347      protected function compileClassFooter(Compiler $compiler)
 348      {
 349          $compiler
 350              ->subcompile($this->getNode('class_end'))
 351              ->outdent()
 352              ->write("}\n")
 353          ;
 354      }
 355  
 356      protected function compileMacros(Compiler $compiler)
 357      {
 358          $compiler->subcompile($this->getNode('macros'));
 359      }
 360  
 361      protected function compileGetTemplateName(Compiler $compiler)
 362      {
 363          $compiler
 364              ->write("public function getTemplateName()\n", "{\n")
 365              ->indent()
 366              ->write('return ')
 367              ->repr($this->getSourceContext()->getName())
 368              ->raw(";\n")
 369              ->outdent()
 370              ->write("}\n\n")
 371          ;
 372      }
 373  
 374      protected function compileIsTraitable(Compiler $compiler)
 375      {
 376          // A template can be used as a trait if:
 377          //   * it has no parent
 378          //   * it has no macros
 379          //   * it has no body
 380          //
 381          // Put another way, a template can be used as a trait if it
 382          // only contains blocks and use statements.
 383          $traitable = !$this->hasNode('parent') && 0 === \count($this->getNode('macros'));
 384          if ($traitable) {
 385              if ($this->getNode('body') instanceof BodyNode) {
 386                  $nodes = $this->getNode('body')->getNode(0);
 387              } else {
 388                  $nodes = $this->getNode('body');
 389              }
 390  
 391              if (!\count($nodes)) {
 392                  $nodes = new Node([$nodes]);
 393              }
 394  
 395              foreach ($nodes as $node) {
 396                  if (!\count($node)) {
 397                      continue;
 398                  }
 399  
 400                  if ($node instanceof TextNode && ctype_space($node->getAttribute('data'))) {
 401                      continue;
 402                  }
 403  
 404                  if ($node instanceof BlockReferenceNode) {
 405                      continue;
 406                  }
 407  
 408                  $traitable = false;
 409                  break;
 410              }
 411          }
 412  
 413          if ($traitable) {
 414              return;
 415          }
 416  
 417          $compiler
 418              ->write("public function isTraitable()\n", "{\n")
 419              ->indent()
 420              ->write(sprintf("return %s;\n", $traitable ? 'true' : 'false'))
 421              ->outdent()
 422              ->write("}\n\n")
 423          ;
 424      }
 425  
 426      protected function compileDebugInfo(Compiler $compiler)
 427      {
 428          $compiler
 429              ->write("public function getDebugInfo()\n", "{\n")
 430              ->indent()
 431              ->write(sprintf("return %s;\n", str_replace("\n", '', var_export(array_reverse($compiler->getDebugInfo(), true), true))))
 432              ->outdent()
 433              ->write("}\n\n")
 434          ;
 435      }
 436  
 437      protected function compileGetSourceContext(Compiler $compiler)
 438      {
 439          $compiler
 440              ->write("public function getSourceContext()\n", "{\n")
 441              ->indent()
 442              ->write('return new Source(')
 443              ->string($compiler->getEnvironment()->isDebug() ? $this->getSourceContext()->getCode() : '')
 444              ->raw(', ')
 445              ->string($this->getSourceContext()->getName())
 446              ->raw(', ')
 447              ->string($this->getSourceContext()->getPath())
 448              ->raw(");\n")
 449              ->outdent()
 450              ->write("}\n")
 451          ;
 452      }
 453  
 454      protected function compileLoadTemplate(Compiler $compiler, $node, $var)
 455      {
 456          if ($node instanceof ConstantExpression) {
 457              $compiler
 458                  ->write(sprintf('%s = $this->loadTemplate(', $var))
 459                  ->subcompile($node)
 460                  ->raw(', ')
 461                  ->repr($node->getTemplateName())
 462                  ->raw(', ')
 463                  ->repr($node->getTemplateLine())
 464                  ->raw(");\n")
 465              ;
 466          } else {
 467              throw new \LogicException('Trait templates can only be constant nodes.');
 468          }
 469      }
 470  }
 471  
 472  class_alias('Twig\Node\ModuleNode', 'Twig_Node_Module');


Generated: Wed Nov 11 20:28:18 2020 Cross-referenced by PHPXref 0.7.1