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

ClassNotFoundFatalErrorHandler.php

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


 001  <?php
 002   
 003  /*
 004   * This file is part of the Symfony package.
 005   *
 006   * (c) Fabien Potencier <fabien@symfony.com>
 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 Symfony\Component\Debug\FatalErrorHandler;
 013   
 014  use Composer\Autoload\ClassLoader as ComposerClassLoader;
 015  use Symfony\Component\ClassLoader\ClassLoader as SymfonyClassLoader;
 016  use Symfony\Component\Debug\DebugClassLoader;
 017  use Symfony\Component\Debug\Exception\ClassNotFoundException;
 018  use Symfony\Component\Debug\Exception\FatalErrorException;
 019   
 020  /**
 021   * ErrorHandler for classes that do not exist.
 022   *
 023   * @author Fabien Potencier <fabien@symfony.com>
 024   */
 025  class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
 026  {
 027      /**
 028       * {@inheritdoc}
 029       */
 030      public function handleError(array $error, FatalErrorException $exception)
 031      {
 032          if (!preg_match('/^(Class|Interface|Trait) [\'"]([^\'"]+)[\'"] not found$/', $error['message'], $matches)) {
 033              return null;
 034          }
 035          $typeName = strtolower($matches[1]);
 036          $fullyQualifiedClassName = $matches[2];
 037   
 038          if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) {
 039              $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1);
 040              $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex);
 041              $message = sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix);
 042              $tail = ' for another namespace?';
 043          } else {
 044              $className = $fullyQualifiedClassName;
 045              $message = sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className);
 046              $tail = '?';
 047          }
 048   
 049          if ($candidates = $this->getClassCandidates($className)) {
 050              $tail = array_pop($candidates).'"?';
 051              if ($candidates) {
 052                  $tail = ' for e.g. "'.implode('", "', $candidates).'" or "'.$tail;
 053              } else {
 054                  $tail = ' for "'.$tail;
 055              }
 056          }
 057          $message .= "\nDid you forget a \"use\" statement".$tail;
 058   
 059          return new ClassNotFoundException($message, $exception);
 060      }
 061   
 062      /**
 063       * Tries to guess the full namespace for a given class name.
 064       *
 065       * By default, it looks for PSR-0 and PSR-4 classes registered via a Symfony or a Composer
 066       * autoloader (that should cover all common cases).
 067       *
 068       * @param string $class A class name (without its namespace)
 069       *
 070       * @return array An array of possible fully qualified class names
 071       */
 072      private function getClassCandidates($class)
 073      {
 074          if (!\is_array($functions = spl_autoload_functions())) {
 075              return [];
 076          }
 077   
 078          // find Symfony and Composer autoloaders
 079          $classes = [];
 080   
 081          foreach ($functions as $function) {
 082              if (!\is_array($function)) {
 083                  continue;
 084              }
 085              // get class loaders wrapped by DebugClassLoader
 086              if ($function[0] instanceof DebugClassLoader) {
 087                  $function = $function[0]->getClassLoader();
 088   
 089                  if (!\is_array($function)) {
 090                      continue;
 091                  }
 092              }
 093   
 094              if ($function[0] instanceof ComposerClassLoader || $function[0] instanceof SymfonyClassLoader) {
 095                  foreach ($function[0]->getPrefixes() as $prefix => $paths) {
 096                      foreach ($paths as $path) {
 097                          $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
 098                      }
 099                  }
 100              }
 101              if ($function[0] instanceof ComposerClassLoader) {
 102                  foreach ($function[0]->getPrefixesPsr4() as $prefix => $paths) {
 103                      foreach ($paths as $path) {
 104                          $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
 105                      }
 106                  }
 107              }
 108          }
 109   
 110          return array_unique($classes);
 111      }
 112   
 113      /**
 114       * @param string $path
 115       * @param string $class
 116       * @param string $prefix
 117       *
 118       * @return array
 119       */
 120      private function findClassInPath($path, $class, $prefix)
 121      {
 122          if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.\dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) {
 123              return [];
 124          }
 125   
 126          $classes = [];
 127          $filename = $class.'.php';
 128          foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
 129              if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) {
 130                  $classes[] = $class;
 131              }
 132          }
 133   
 134          return $classes;
 135      }
 136   
 137      /**
 138       * @param string $path
 139       * @param string $file
 140       * @param string $prefix
 141       *
 142       * @return string|null
 143       */
 144      private function convertFileToClass($path, $file, $prefix)
 145      {
 146          $candidates = [
 147              // namespaced class
 148              $namespacedClass = str_replace([$path.\DIRECTORY_SEPARATOR, '.php', '/'], ['', '', '\\'], $file),
 149              // namespaced class (with target dir)
 150              $prefix.$namespacedClass,
 151              // namespaced class (with target dir and separator)
 152              $prefix.'\\'.$namespacedClass,
 153              // PEAR class
 154              str_replace('\\', '_', $namespacedClass),
 155              // PEAR class (with target dir)
 156              str_replace('\\', '_', $prefix.$namespacedClass),
 157              // PEAR class (with target dir and separator)
 158              str_replace('\\', '_', $prefix.'\\'.$namespacedClass),
 159          ];
 160   
 161          if ($prefix) {
 162              $candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); });
 163          }
 164   
 165          // We cannot use the autoloader here as most of them use require; but if the class
 166          // is not found, the new autoloader call will require the file again leading to a
 167          // "cannot redeclare class" error.
 168          foreach ($candidates as $candidate) {
 169              if ($this->classExists($candidate)) {
 170                  return $candidate;
 171              }
 172          }
 173   
 174          try {
 175              require_once $file;
 176          } catch (\Throwable $e) {
 177              return null;
 178          }
 179   
 180          foreach ($candidates as $candidate) {
 181              if ($this->classExists($candidate)) {
 182                  return $candidate;
 183              }
 184          }
 185   
 186          return null;
 187      }
 188   
 189      /**
 190       * @param string $class
 191       *
 192       * @return bool
 193       */
 194      private function classExists($class)
 195      {
 196          return class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false);
 197      }
 198  }
 199