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