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

ModuleNode.php

Zuletzt modifiziert: 02.04.2025, 15:03 - Dateigröße: 14.78 KiB


001  <?php
002   
003  /*
004   * This file is part of Twig.
005   *
006   * (c) Fabien Potencier
007   * (c) Armin Ronacher
008   *
009   * For the full copyright and license information, please view the LICENSE
010   * file that was distributed with this source code.
011   */
012   
013  namespace Twig\Node;
014   
015  use Twig\Compiler;
016  use Twig\Node\Expression\AbstractExpression;
017  use Twig\Node\Expression\ConstantExpression;
018  use Twig\Source;
019   
020  /**
021   * Represents a module node.
022   *
023   * Consider this class as being final. If you need to customize the behavior of
024   * the generated class, consider adding nodes to the following nodes: display_start,
025   * display_end, constructor_start, constructor_end, and class_end.
026   *
027   * @author Fabien Potencier <fabien@symfony.com>
028   *
029   * @final since Twig 2.4.0
030   */
031  class ModuleNode extends Node
032  {
033      public function __construct(Node $body, ?AbstractExpression $parent, Node $blocks, Node $macros, Node $traits, $embeddedTemplates, Source $source)
034      {
035          if (__CLASS__ !== static::class) {
036              @trigger_error('Overriding '.__CLASS__.' is deprecated since Twig 2.4.0 and the class will be final in 3.0.', \E_USER_DEPRECATED);
037          }
038   
039          $nodes = [
040              'body' => $body,
041              'blocks' => $blocks,
042              'macros' => $macros,
043              'traits' => $traits,
044              'display_start' => new Node(),
045              'display_end' => new Node(),
046              'constructor_start' => new Node(),
047              'constructor_end' => new Node(),
048              'class_end' => new Node(),
049          ];
050          if (null !== $parent) {
051              $nodes['parent'] = $parent;
052          }
053   
054          // embedded templates are set as attributes so that they are only visited once by the visitors
055          parent::__construct($nodes, [
056              'index' => null,
057              'embedded_templates' => $embeddedTemplates,
058          ], 1);
059   
060          // populate the template name of all node children
061          $this->setSourceContext($source);
062      }
063   
064      public function setIndex($index)
065      {
066          $this->setAttribute('index', $index);
067      }
068   
069      public function compile(Compiler $compiler)
070      {
071          $this->compileTemplate($compiler);
072   
073          foreach ($this->getAttribute('embedded_templates') as $template) {
074              $compiler->subcompile($template);
075          }
076      }
077   
078      protected function compileTemplate(Compiler $compiler)
079      {
080          if (!$this->getAttribute('index')) {
081              $compiler->write('<?php');
082          }
083   
084          $this->compileClassHeader($compiler);
085   
086          $this->compileConstructor($compiler);
087   
088          $this->compileGetParent($compiler);
089   
090          $this->compileDisplay($compiler);
091   
092          $compiler->subcompile($this->getNode('blocks'));
093   
094          $this->compileMacros($compiler);
095   
096          $this->compileGetTemplateName($compiler);
097   
098          $this->compileIsTraitable($compiler);
099   
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');
473