Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

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: 02.04.2025, 15:03 - 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