Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

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