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

ExtensionSet.php

Zuletzt modifiziert: 01.05.2026, 11:26 - Dateigröße: 12.58 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;
 013   
 014  use Twig\Error\RuntimeError;
 015  use Twig\Extension\ExtensionInterface;
 016  use Twig\Extension\GlobalsInterface;
 017  use Twig\Extension\InitRuntimeInterface;
 018  use Twig\Extension\StagingExtension;
 019  use Twig\NodeVisitor\NodeVisitorInterface;
 020  use Twig\TokenParser\TokenParserInterface;
 021   
 022  /**
 023   * @author Fabien Potencier <fabien@symfony.com>
 024   *
 025   * @internal
 026   */
 027  final class ExtensionSet
 028  {
 029      private $extensions;
 030      private $initialized = false;
 031      private $runtimeInitialized = false;
 032      private $staging;
 033      private $parsers;
 034      private $visitors;
 035      private $filters;
 036      private $tests;
 037      private $functions;
 038      private $unaryOperators;
 039      private $binaryOperators;
 040      private $globals;
 041      private $functionCallbacks = [];
 042      private $filterCallbacks = [];
 043      private $lastModified = 0;
 044   
 045      public function __construct()
 046      {
 047          $this->staging = new StagingExtension();
 048      }
 049   
 050      /**
 051       * Initializes the runtime environment.
 052       *
 053       * @deprecated since Twig 2.7
 054       */
 055      public function initRuntime(Environment $env)
 056      {
 057          if ($this->runtimeInitialized) {
 058              return;
 059          }
 060   
 061          $this->runtimeInitialized = true;
 062   
 063          foreach ($this->extensions as $extension) {
 064              if ($extension instanceof InitRuntimeInterface) {
 065                  $extension->initRuntime($env);
 066              }
 067          }
 068      }
 069   
 070      public function hasExtension(string $class): bool
 071      {
 072          $class = ltrim($class, '\\');
 073          if (!isset($this->extensions[$class]) && class_exists($class, false)) {
 074              // For BC/FC with namespaced aliases
 075              $class = (new \ReflectionClass($class))->name;
 076          }
 077   
 078          return isset($this->extensions[$class]);
 079      }
 080   
 081      public function getExtension(string $class): ExtensionInterface
 082      {
 083          $class = ltrim($class, '\\');
 084          if (!isset($this->extensions[$class]) && class_exists($class, false)) {
 085              // For BC/FC with namespaced aliases
 086              $class = (new \ReflectionClass($class))->name;
 087          }
 088   
 089          if (!isset($this->extensions[$class])) {
 090              throw new RuntimeError(sprintf('The "%s" extension is not enabled.', $class));
 091          }
 092   
 093          return $this->extensions[$class];
 094      }
 095   
 096      /**
 097       * @param ExtensionInterface[] $extensions
 098       */
 099      public function setExtensions(array $extensions)
 100      {
 101          foreach ($extensions as $extension) {
 102              $this->addExtension($extension);
 103          }
 104      }
 105   
 106      /**
 107       * @return ExtensionInterface[]
 108       */
 109      public function getExtensions(): array
 110      {
 111          return $this->extensions;
 112      }
 113   
 114      public function getSignature(): string
 115      {
 116          return json_encode(array_keys($this->extensions));
 117      }
 118   
 119      public function isInitialized(): bool
 120      {
 121          return $this->initialized || $this->runtimeInitialized;
 122      }
 123   
 124      public function getLastModified(): int
 125      {
 126          if (0 !== $this->lastModified) {
 127              return $this->lastModified;
 128          }
 129   
 130          foreach ($this->extensions as $extension) {
 131              $r = new \ReflectionObject($extension);
 132              if (file_exists($r->getFileName()) && ($extensionTime = filemtime($r->getFileName())) > $this->lastModified) {
 133                  $this->lastModified = $extensionTime;
 134              }
 135          }
 136   
 137          return $this->lastModified;
 138      }
 139   
 140      public function addExtension(ExtensionInterface $extension)
 141      {
 142          $class = \get_class($extension);
 143   
 144          if ($this->initialized) {
 145              throw new \LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $class));
 146          }
 147   
 148          if (isset($this->extensions[$class])) {
 149              throw new \LogicException(sprintf('Unable to register extension "%s" as it is already registered.', $class));
 150          }
 151   
 152          $this->extensions[$class] = $extension;
 153      }
 154   
 155      public function addFunction(TwigFunction $function)
 156      {
 157          if ($this->initialized) {
 158              throw new \LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.', $function->getName()));
 159          }
 160   
 161          $this->staging->addFunction($function);
 162      }
 163   
 164      /**
 165       * @return TwigFunction[]
 166       */
 167      public function getFunctions(): array
 168      {
 169          if (!$this->initialized) {
 170              $this->initExtensions();
 171          }
 172   
 173          return $this->functions;
 174      }
 175   
 176      /**
 177       * @return TwigFunction|false
 178       */
 179      public function getFunction(string $name)
 180      {
 181          if (!$this->initialized) {
 182              $this->initExtensions();
 183          }
 184   
 185          if (isset($this->functions[$name])) {
 186              return $this->functions[$name];
 187          }
 188   
 189          foreach ($this->functions as $pattern => $function) {
 190              $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count);
 191   
 192              if ($count && preg_match('#^'.$pattern.'$#', $name, $matches)) {
 193                  array_shift($matches);
 194                  $function->setArguments($matches);
 195   
 196                  return $function;
 197              }
 198          }
 199   
 200          foreach ($this->functionCallbacks as $callback) {
 201              if (false !== $function = $callback($name)) {
 202                  return $function;
 203              }
 204          }
 205   
 206          return false;
 207      }
 208   
 209      public function registerUndefinedFunctionCallback(callable $callable)
 210      {
 211          $this->functionCallbacks[] = $callable;
 212      }
 213   
 214      public function addFilter(TwigFilter $filter)
 215      {
 216          if ($this->initialized) {
 217              throw new \LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.', $filter->getName()));
 218          }
 219   
 220          $this->staging->addFilter($filter);
 221      }
 222   
 223      /**
 224       * @return TwigFilter[]
 225       */
 226      public function getFilters(): array
 227      {
 228          if (!$this->initialized) {
 229              $this->initExtensions();
 230          }
 231   
 232          return $this->filters;
 233      }
 234   
 235      /**
 236       * @return TwigFilter|false
 237       */
 238      public function getFilter(string $name)
 239      {
 240          if (!$this->initialized) {
 241              $this->initExtensions();
 242          }
 243   
 244          if (isset($this->filters[$name])) {
 245              return $this->filters[$name];
 246          }
 247   
 248          foreach ($this->filters as $pattern => $filter) {
 249              $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count);
 250   
 251              if ($count && preg_match('#^'.$pattern.'$#', $name, $matches)) {
 252                  array_shift($matches);
 253                  $filter->setArguments($matches);
 254   
 255                  return $filter;
 256              }
 257          }
 258   
 259          foreach ($this->filterCallbacks as $callback) {
 260              if (false !== $filter = $callback($name)) {
 261                  return $filter;
 262              }
 263          }
 264   
 265          return false;
 266      }
 267   
 268      public function registerUndefinedFilterCallback(callable $callable)
 269      {
 270          $this->filterCallbacks[] = $callable;
 271      }
 272   
 273      public function addNodeVisitor(NodeVisitorInterface $visitor)
 274      {
 275          if ($this->initialized) {
 276              throw new \LogicException('Unable to add a node visitor as extensions have already been initialized.');
 277          }
 278   
 279          $this->staging->addNodeVisitor($visitor);
 280      }
 281   
 282      /**
 283       * @return NodeVisitorInterface[]
 284       */
 285      public function getNodeVisitors(): array
 286      {
 287          if (!$this->initialized) {
 288              $this->initExtensions();
 289          }
 290   
 291          return $this->visitors;
 292      }
 293   
 294      public function addTokenParser(TokenParserInterface $parser)
 295      {
 296          if ($this->initialized) {
 297              throw new \LogicException('Unable to add a token parser as extensions have already been initialized.');
 298          }
 299   
 300          $this->staging->addTokenParser($parser);
 301      }
 302   
 303      /**
 304       * @return TokenParserInterface[]
 305       */
 306      public function getTokenParsers(): array
 307      {
 308          if (!$this->initialized) {
 309              $this->initExtensions();
 310          }
 311   
 312          return $this->parsers;
 313      }
 314   
 315      public function getGlobals(): array
 316      {
 317          if (null !== $this->globals) {
 318              return $this->globals;
 319          }
 320   
 321          $globals = [];
 322          foreach ($this->extensions as $extension) {
 323              if (!$extension instanceof GlobalsInterface) {
 324                  continue;
 325              }
 326   
 327              $extGlobals = $extension->getGlobals();
 328              if (!\is_array($extGlobals)) {
 329                  throw new \UnexpectedValueException(sprintf('"%s::getGlobals()" must return an array of globals.', \get_class($extension)));
 330              }
 331   
 332              $globals = array_merge($globals, $extGlobals);
 333          }
 334   
 335          if ($this->initialized) {
 336              $this->globals = $globals;
 337          }
 338   
 339          return $globals;
 340      }
 341   
 342      public function addTest(TwigTest $test)
 343      {
 344          if ($this->initialized) {
 345              throw new \LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.', $test->getName()));
 346          }
 347   
 348          $this->staging->addTest($test);
 349      }
 350   
 351      /**
 352       * @return TwigTest[]
 353       */
 354      public function getTests(): array
 355      {
 356          if (!$this->initialized) {
 357              $this->initExtensions();
 358          }
 359   
 360          return $this->tests;
 361      }
 362   
 363      /**
 364       * @return TwigTest|false
 365       */
 366      public function getTest(string $name)
 367      {
 368          if (!$this->initialized) {
 369              $this->initExtensions();
 370          }
 371   
 372          if (isset($this->tests[$name])) {
 373              return $this->tests[$name];
 374          }
 375   
 376          foreach ($this->tests as $pattern => $test) {
 377              $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count);
 378   
 379              if ($count) {
 380                  if (preg_match('#^'.$pattern.'$#', $name, $matches)) {
 381                      array_shift($matches);
 382                      $test->setArguments($matches);
 383   
 384                      return $test;
 385                  }
 386              }
 387          }
 388   
 389          return false;
 390      }
 391   
 392      public function getUnaryOperators(): array
 393      {
 394          if (!$this->initialized) {
 395              $this->initExtensions();
 396          }
 397   
 398          return $this->unaryOperators;
 399      }
 400   
 401      public function getBinaryOperators(): array
 402      {
 403          if (!$this->initialized) {
 404              $this->initExtensions();
 405          }
 406   
 407          return $this->binaryOperators;
 408      }
 409   
 410      private function initExtensions()
 411      {
 412          $this->parsers = [];
 413          $this->filters = [];
 414          $this->functions = [];
 415          $this->tests = [];
 416          $this->visitors = [];
 417          $this->unaryOperators = [];
 418          $this->binaryOperators = [];
 419   
 420          foreach ($this->extensions as $extension) {
 421              $this->initExtension($extension);
 422          }
 423          $this->initExtension($this->staging);
 424          // Done at the end only, so that an exception during initialization does not mark the environment as initialized when catching the exception
 425          $this->initialized = true;
 426      }
 427   
 428      private function initExtension(ExtensionInterface $extension)
 429      {
 430          // filters
 431          foreach ($extension->getFilters() as $filter) {
 432              $this->filters[$filter->getName()] = $filter;
 433          }
 434   
 435          // functions
 436          foreach ($extension->getFunctions() as $function) {
 437              $this->functions[$function->getName()] = $function;
 438          }
 439   
 440          // tests
 441          foreach ($extension->getTests() as $test) {
 442              $this->tests[$test->getName()] = $test;
 443          }
 444   
 445          // token parsers
 446          foreach ($extension->getTokenParsers() as $parser) {
 447              if (!$parser instanceof TokenParserInterface) {
 448                  throw new \LogicException('getTokenParsers() must return an array of \Twig\TokenParser\TokenParserInterface.');
 449              }
 450   
 451              $this->parsers[] = $parser;
 452          }
 453   
 454          // node visitors
 455          foreach ($extension->getNodeVisitors() as $visitor) {
 456              $this->visitors[] = $visitor;
 457          }
 458   
 459          // operators
 460          if ($operators = $extension->getOperators()) {
 461              if (!\is_array($operators)) {
 462                  throw new \InvalidArgumentException(sprintf('"%s::getOperators()" must return an array with operators, got "%s".', \get_class($extension), \is_object($operators) ? \get_class($operators) : \gettype($operators).(\is_resource($operators) ? '' : '#'.$operators)));
 463              }
 464   
 465              if (2 !== \count($operators)) {
 466                  throw new \InvalidArgumentException(sprintf('"%s::getOperators()" must return an array of 2 elements, got %d.', \get_class($extension), \count($operators)));
 467              }
 468   
 469              $this->unaryOperators = array_merge($this->unaryOperators, $operators[0]);
 470              $this->binaryOperators = array_merge($this->binaryOperators, $operators[1]);
 471          }
 472      }
 473  }
 474   
 475  class_alias('Twig\ExtensionSet', 'Twig_ExtensionSet');
 476