Verzeichnisstruktur phpBB-3.3.16


Veröffentlicht
27.04.2026

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

OptimizerNodeVisitor.php

Zuletzt modifiziert: 01.05.2026, 11:27 - Dateigröße: 6.61 KiB


 001  <?php
 002   
 003  /*
 004   * This file is part of Twig.
 005   *
 006   * (c) Fabien Potencier
 007   *
 008   * For the full copyright and license information, please view the LICENSE
 009   * file that was distributed with this source code.
 010   */
 011   
 012  namespace Twig\NodeVisitor;
 013   
 014  use Twig\Environment;
 015  use Twig\Node\BlockReferenceNode;
 016  use Twig\Node\Expression\BlockReferenceExpression;
 017  use Twig\Node\Expression\ConstantExpression;
 018  use Twig\Node\Expression\FilterExpression;
 019  use Twig\Node\Expression\FunctionExpression;
 020  use Twig\Node\Expression\GetAttrExpression;
 021  use Twig\Node\Expression\NameExpression;
 022  use Twig\Node\Expression\ParentExpression;
 023  use Twig\Node\ForNode;
 024  use Twig\Node\IncludeNode;
 025  use Twig\Node\Node;
 026  use Twig\Node\PrintNode;
 027   
 028  /**
 029   * Tries to optimize the AST.
 030   *
 031   * This visitor is always the last registered one.
 032   *
 033   * You can configure which optimizations you want to activate via the
 034   * optimizer mode.
 035   *
 036   * @author Fabien Potencier <fabien@symfony.com>
 037   */
 038  final class OptimizerNodeVisitor extends AbstractNodeVisitor
 039  {
 040      public const OPTIMIZE_ALL = -1;
 041      public const OPTIMIZE_NONE = 0;
 042      public const OPTIMIZE_FOR = 2;
 043      public const OPTIMIZE_RAW_FILTER = 4;
 044      // obsolete, does not do anything
 045      public const OPTIMIZE_VAR_ACCESS = 8;
 046   
 047      private $loops = [];
 048      private $loopsTargets = [];
 049      private $optimizers;
 050   
 051      /**
 052       * @param int $optimizers The optimizer mode
 053       */
 054      public function __construct(int $optimizers = -1)
 055      {
 056          if (!\is_int($optimizers) || $optimizers > (self::OPTIMIZE_FOR | self::OPTIMIZE_RAW_FILTER | self::OPTIMIZE_VAR_ACCESS)) {
 057              throw new \InvalidArgumentException(sprintf('Optimizer mode "%s" is not valid.', $optimizers));
 058          }
 059   
 060          $this->optimizers = $optimizers;
 061      }
 062   
 063      protected function doEnterNode(Node $node, Environment $env)
 064      {
 065          if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) {
 066              $this->enterOptimizeFor($node, $env);
 067          }
 068   
 069          return $node;
 070      }
 071   
 072      protected function doLeaveNode(Node $node, Environment $env)
 073      {
 074          if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) {
 075              $this->leaveOptimizeFor($node, $env);
 076          }
 077   
 078          if (self::OPTIMIZE_RAW_FILTER === (self::OPTIMIZE_RAW_FILTER & $this->optimizers)) {
 079              $node = $this->optimizeRawFilter($node, $env);
 080          }
 081   
 082          $node = $this->optimizePrintNode($node, $env);
 083   
 084          return $node;
 085      }
 086   
 087      /**
 088       * Optimizes print nodes.
 089       *
 090       * It replaces:
 091       *
 092       *   * "echo $this->render(Parent)Block()" with "$this->display(Parent)Block()"
 093       */
 094      private function optimizePrintNode(Node $node, Environment $env): Node
 095      {
 096          if (!$node instanceof PrintNode) {
 097              return $node;
 098          }
 099   
 100          $exprNode = $node->getNode('expr');
 101          if (
 102              $exprNode instanceof BlockReferenceExpression ||
 103              $exprNode instanceof ParentExpression
 104          ) {
 105              $exprNode->setAttribute('output', true);
 106   
 107              return $exprNode;
 108          }
 109   
 110          return $node;
 111      }
 112   
 113      /**
 114       * Removes "raw" filters.
 115       */
 116      private function optimizeRawFilter(Node $node, Environment $env): Node
 117      {
 118          if ($node instanceof FilterExpression && 'raw' == $node->getNode('filter')->getAttribute('value')) {
 119              return $node->getNode('node');
 120          }
 121   
 122          return $node;
 123      }
 124   
 125      /**
 126       * Optimizes "for" tag by removing the "loop" variable creation whenever possible.
 127       */
 128      private function enterOptimizeFor(Node $node, Environment $env)
 129      {
 130          if ($node instanceof ForNode) {
 131              // disable the loop variable by default
 132              $node->setAttribute('with_loop', false);
 133              array_unshift($this->loops, $node);
 134              array_unshift($this->loopsTargets, $node->getNode('value_target')->getAttribute('name'));
 135              array_unshift($this->loopsTargets, $node->getNode('key_target')->getAttribute('name'));
 136          } elseif (!$this->loops) {
 137              // we are outside a loop
 138              return;
 139          }
 140   
 141          // when do we need to add the loop variable back?
 142   
 143          // the loop variable is referenced for the current loop
 144          elseif ($node instanceof NameExpression && 'loop' === $node->getAttribute('name')) {
 145              $node->setAttribute('always_defined', true);
 146              $this->addLoopToCurrent();
 147          }
 148   
 149          // optimize access to loop targets
 150          elseif ($node instanceof NameExpression && \in_array($node->getAttribute('name'), $this->loopsTargets)) {
 151              $node->setAttribute('always_defined', true);
 152          }
 153   
 154          // block reference
 155          elseif ($node instanceof BlockReferenceNode || $node instanceof BlockReferenceExpression) {
 156              $this->addLoopToCurrent();
 157          }
 158   
 159          // include without the only attribute
 160          elseif ($node instanceof IncludeNode && !$node->getAttribute('only')) {
 161              $this->addLoopToAll();
 162          }
 163   
 164          // include function without the with_context=false parameter
 165          elseif ($node instanceof FunctionExpression
 166              && 'include' === $node->getAttribute('name')
 167              && (!$node->getNode('arguments')->hasNode('with_context')
 168                   || false !== $node->getNode('arguments')->getNode('with_context')->getAttribute('value')
 169                 )
 170          ) {
 171              $this->addLoopToAll();
 172          }
 173   
 174          // the loop variable is referenced via an attribute
 175          elseif ($node instanceof GetAttrExpression
 176              && (!$node->getNode('attribute') instanceof ConstantExpression
 177                  || 'parent' === $node->getNode('attribute')->getAttribute('value')
 178                 )
 179              && (true === $this->loops[0]->getAttribute('with_loop')
 180                  || ($node->getNode('node') instanceof NameExpression
 181                      && 'loop' === $node->getNode('node')->getAttribute('name')
 182                     )
 183                 )
 184          ) {
 185              $this->addLoopToAll();
 186          }
 187      }
 188   
 189      /**
 190       * Optimizes "for" tag by removing the "loop" variable creation whenever possible.
 191       */
 192      private function leaveOptimizeFor(Node $node, Environment $env)
 193      {
 194          if ($node instanceof ForNode) {
 195              array_shift($this->loops);
 196              array_shift($this->loopsTargets);
 197              array_shift($this->loopsTargets);
 198          }
 199      }
 200   
 201      private function addLoopToCurrent()
 202      {
 203          $this->loops[0]->setAttribute('with_loop', true);
 204      }
 205   
 206      private function addLoopToAll()
 207      {
 208          foreach ($this->loops as $loop) {
 209              $loop->setAttribute('with_loop', true);
 210          }
 211      }
 212   
 213      public function getPriority()
 214      {
 215          return 255;
 216      }
 217  }
 218   
 219  class_alias('Twig\NodeVisitor\OptimizerNodeVisitor', 'Twig_NodeVisitor_Optimizer');
 220