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

FilesystemLoader.php

Zuletzt modifiziert: 01.05.2026, 11:27 - Dateigröße: 8.62 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\Loader;
 013   
 014  use Twig\Error\LoaderError;
 015  use Twig\Source;
 016   
 017  /**
 018   * Loads template from the filesystem.
 019   *
 020   * @author Fabien Potencier <fabien@symfony.com>
 021   */
 022  class FilesystemLoader implements LoaderInterface, ExistsLoaderInterface, SourceContextLoaderInterface
 023  {
 024      /** Identifier of the main namespace. */
 025      public const MAIN_NAMESPACE = '__main__';
 026   
 027      protected $paths = [];
 028      protected $cache = [];
 029      protected $errorCache = [];
 030   
 031      private $rootPath;
 032   
 033      /**
 034       * @param string|array $paths    A path or an array of paths where to look for templates
 035       * @param string|null  $rootPath The root path common to all relative paths (null for getcwd())
 036       */
 037      public function __construct($paths = [], string $rootPath = null)
 038      {
 039          $this->rootPath = (null === $rootPath ? getcwd() : $rootPath).\DIRECTORY_SEPARATOR;
 040          if (null !== $rootPath && false !== ($realPath = realpath($rootPath))) {
 041              $this->rootPath = $realPath.\DIRECTORY_SEPARATOR;
 042          }
 043   
 044          if ($paths) {
 045              $this->setPaths($paths);
 046          }
 047      }
 048   
 049      /**
 050       * Returns the paths to the templates.
 051       *
 052       * @param string $namespace A path namespace
 053       *
 054       * @return array The array of paths where to look for templates
 055       */
 056      public function getPaths($namespace = self::MAIN_NAMESPACE)
 057      {
 058          return isset($this->paths[$namespace]) ? $this->paths[$namespace] : [];
 059      }
 060   
 061      /**
 062       * Returns the path namespaces.
 063       *
 064       * The main namespace is always defined.
 065       *
 066       * @return array The array of defined namespaces
 067       */
 068      public function getNamespaces()
 069      {
 070          return array_keys($this->paths);
 071      }
 072   
 073      /**
 074       * Sets the paths where templates are stored.
 075       *
 076       * @param string|array $paths     A path or an array of paths where to look for templates
 077       * @param string       $namespace A path namespace
 078       */
 079      public function setPaths($paths, $namespace = self::MAIN_NAMESPACE)
 080      {
 081          if (!\is_array($paths)) {
 082              $paths = [$paths];
 083          }
 084   
 085          $this->paths[$namespace] = [];
 086          foreach ($paths as $path) {
 087              $this->addPath($path, $namespace);
 088          }
 089      }
 090   
 091      /**
 092       * Adds a path where templates are stored.
 093       *
 094       * @param string $path      A path where to look for templates
 095       * @param string $namespace A path namespace
 096       *
 097       * @throws LoaderError
 098       */
 099      public function addPath($path, $namespace = self::MAIN_NAMESPACE)
 100      {
 101          // invalidate the cache
 102          $this->cache = $this->errorCache = [];
 103   
 104          $checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path;
 105          if (!is_dir($checkPath)) {
 106              throw new LoaderError(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath));
 107          }
 108   
 109          $this->paths[$namespace][] = rtrim($path, '/\\');
 110      }
 111   
 112      /**
 113       * Prepends a path where templates are stored.
 114       *
 115       * @param string $path      A path where to look for templates
 116       * @param string $namespace A path namespace
 117       *
 118       * @throws LoaderError
 119       */
 120      public function prependPath($path, $namespace = self::MAIN_NAMESPACE)
 121      {
 122          // invalidate the cache
 123          $this->cache = $this->errorCache = [];
 124   
 125          $checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path;
 126          if (!is_dir($checkPath)) {
 127              throw new LoaderError(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath));
 128          }
 129   
 130          $path = rtrim($path, '/\\');
 131   
 132          if (!isset($this->paths[$namespace])) {
 133              $this->paths[$namespace][] = $path;
 134          } else {
 135              array_unshift($this->paths[$namespace], $path);
 136          }
 137      }
 138   
 139      public function getSourceContext($name)
 140      {
 141          if (null === ($path = $this->findTemplate($name)) || false === $path) {
 142              return new Source('', $name, '');
 143          }
 144   
 145          return new Source(file_get_contents($path), $name, $path);
 146      }
 147   
 148      public function getCacheKey($name)
 149      {
 150          if (null === ($path = $this->findTemplate($name)) || false === $path) {
 151              return '';
 152          }
 153          $len = \strlen($this->rootPath);
 154          if (0 === strncmp($this->rootPath, $path, $len)) {
 155              return substr($path, $len);
 156          }
 157   
 158          return $path;
 159      }
 160   
 161      public function exists($name)
 162      {
 163          $name = $this->normalizeName($name);
 164   
 165          if (isset($this->cache[$name])) {
 166              return true;
 167          }
 168   
 169          return null !== ($path = $this->findTemplate($name, false)) && false !== $path;
 170      }
 171   
 172      public function isFresh($name, $time)
 173      {
 174          // false support to be removed in 3.0
 175          if (null === ($path = $this->findTemplate($name)) || false === $path) {
 176              return false;
 177          }
 178   
 179          return filemtime($path) < $time;
 180      }
 181   
 182      /**
 183       * Checks if the template can be found.
 184       *
 185       * In Twig 3.0, findTemplate must return a string or null (returning false won't work anymore).
 186       *
 187       * @param string $name  The template name
 188       * @param bool   $throw Whether to throw an exception when an error occurs
 189       *
 190       * @return string|false|null The template name or false/null
 191       */
 192      protected function findTemplate($name, $throw = true)
 193      {
 194          $name = $this->normalizeName($name);
 195   
 196          if (isset($this->cache[$name])) {
 197              return $this->cache[$name];
 198          }
 199   
 200          if (isset($this->errorCache[$name])) {
 201              if (!$throw) {
 202                  return false;
 203              }
 204   
 205              throw new LoaderError($this->errorCache[$name]);
 206          }
 207   
 208          try {
 209              list($namespace, $shortname) = $this->parseName($name);
 210   
 211              $this->validateName($shortname);
 212          } catch (LoaderError $e) {
 213              if (!$throw) {
 214                  return false;
 215              }
 216   
 217              throw $e;
 218          }
 219   
 220          if (!isset($this->paths[$namespace])) {
 221              $this->errorCache[$name] = sprintf('There are no registered paths for namespace "%s".', $namespace);
 222   
 223              if (!$throw) {
 224                  return false;
 225              }
 226   
 227              throw new LoaderError($this->errorCache[$name]);
 228          }
 229   
 230          foreach ($this->paths[$namespace] as $path) {
 231              if (!$this->isAbsolutePath($path)) {
 232                  $path = $this->rootPath.$path;
 233              }
 234   
 235              if (is_file($path.'/'.$shortname)) {
 236                  if (false !== $realpath = realpath($path.'/'.$shortname)) {
 237                      return $this->cache[$name] = $realpath;
 238                  }
 239   
 240                  return $this->cache[$name] = $path.'/'.$shortname;
 241              }
 242          }
 243   
 244          $this->errorCache[$name] = sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace]));
 245   
 246          if (!$throw) {
 247              return false;
 248          }
 249   
 250          throw new LoaderError($this->errorCache[$name]);
 251      }
 252   
 253      private function normalizeName($name)
 254      {
 255          return preg_replace('#/{2,}#', '/', str_replace('\\', '/', (string) $name));
 256      }
 257   
 258      private function parseName($name, $default = self::MAIN_NAMESPACE)
 259      {
 260          if (isset($name[0]) && '@' == $name[0]) {
 261              if (false === $pos = strpos($name, '/')) {
 262                  throw new LoaderError(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name));
 263              }
 264   
 265              $namespace = substr($name, 1, $pos - 1);
 266              $shortname = substr($name, $pos + 1);
 267   
 268              return [$namespace, $shortname];
 269          }
 270   
 271          return [$default, $name];
 272      }
 273   
 274      private function validateName($name)
 275      {
 276          if (false !== strpos($name, "\0")) {
 277              throw new LoaderError('A template name cannot contain NUL bytes.');
 278          }
 279   
 280          $name = ltrim($name, '/');
 281          $parts = explode('/', $name);
 282          $level = 0;
 283          foreach ($parts as $part) {
 284              if ('..' === $part) {
 285                  --$level;
 286              } elseif ('.' !== $part) {
 287                  ++$level;
 288              }
 289   
 290              if ($level < 0) {
 291                  throw new LoaderError(sprintf('Looks like you try to load a template outside configured directories (%s).', $name));
 292              }
 293          }
 294      }
 295   
 296      private function isAbsolutePath($file)
 297      {
 298          return strspn($file, '/\\', 0, 1)
 299              || (\strlen($file) > 3 && ctype_alpha($file[0])
 300                  && ':' === $file[1]
 301                  && strspn($file, '/\\', 2, 1)
 302              )
 303              || null !== parse_url($file, \PHP_URL_SCHEME)
 304          ;
 305      }
 306  }
 307   
 308  class_alias('Twig\Loader\FilesystemLoader', 'Twig_Loader_Filesystem');
 309