[ Index ]

PHP Cross Reference of phpBB-3.3.14-deutsch

title

Body

[close]

/vendor/symfony/config/Resource/ -> ClassExistenceResource.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of the Symfony package.
   5   *
   6   * (c) Fabien Potencier <fabien@symfony.com>
   7   *
   8   * For the full copyright and license information, please view the LICENSE
   9   * file that was distributed with this source code.
  10   */
  11  
  12  namespace Symfony\Component\Config\Resource;
  13  
  14  /**
  15   * ClassExistenceResource represents a class existence.
  16   * Freshness is only evaluated against resource existence.
  17   *
  18   * The resource must be a fully-qualified class name.
  19   *
  20   * @author Fabien Potencier <fabien@symfony.com>
  21   */
  22  class ClassExistenceResource implements SelfCheckingResourceInterface, \Serializable
  23  {
  24      private $resource;
  25      private $exists;
  26  
  27      private static $autoloadLevel = 0;
  28      private static $autoloadedClass;
  29      private static $existsCache = [];
  30  
  31      /**
  32       * @param string    $resource The fully-qualified class name
  33       * @param bool|null $exists   Boolean when the existency check has already been done
  34       */
  35      public function __construct($resource, $exists = null)
  36      {
  37          $this->resource = $resource;
  38          if (null !== $exists) {
  39              $this->exists = [(bool) $exists, null];
  40          }
  41      }
  42  
  43      /**
  44       * {@inheritdoc}
  45       */
  46      public function __toString()
  47      {
  48          return $this->resource;
  49      }
  50  
  51      /**
  52       * @return string The file path to the resource
  53       */
  54      public function getResource()
  55      {
  56          return $this->resource;
  57      }
  58  
  59      /**
  60       * {@inheritdoc}
  61       *
  62       * @throws \ReflectionException when a parent class/interface/trait is not found
  63       */
  64      public function isFresh($timestamp)
  65      {
  66          $loaded = class_exists($this->resource, false) || interface_exists($this->resource, false) || trait_exists($this->resource, false);
  67  
  68          if (null !== $exists = &self::$existsCache[$this->resource]) {
  69              if ($loaded) {
  70                  $exists = [true, null];
  71              } elseif (0 >= $timestamp && !$exists[0] && null !== $exists[1]) {
  72                  throw new \ReflectionException($exists[1]);
  73              }
  74          } elseif ([false, null] === $exists = [$loaded, null]) {
  75              if (!self::$autoloadLevel++) {
  76                  spl_autoload_register(__CLASS__.'::throwOnRequiredClass');
  77              }
  78              $autoloadedClass = self::$autoloadedClass;
  79              self::$autoloadedClass = ltrim($this->resource, '\\');
  80  
  81              try {
  82                  $exists[0] = class_exists($this->resource) || interface_exists($this->resource, false) || trait_exists($this->resource, false);
  83              } catch (\Exception $e) {
  84                  $exists[1] = $e->getMessage();
  85  
  86                  try {
  87                      self::throwOnRequiredClass($this->resource, $e);
  88                  } catch (\ReflectionException $e) {
  89                      if (0 >= $timestamp) {
  90                          throw $e;
  91                      }
  92                  }
  93              } catch (\Throwable $e) {
  94                  $exists[1] = $e->getMessage();
  95  
  96                  throw $e;
  97              } finally {
  98                  self::$autoloadedClass = $autoloadedClass;
  99                  if (!--self::$autoloadLevel) {
 100                      spl_autoload_unregister(__CLASS__.'::throwOnRequiredClass');
 101                  }
 102              }
 103          }
 104  
 105          if (null === $this->exists) {
 106              $this->exists = $exists;
 107          }
 108  
 109          return $this->exists[0] xor !$exists[0];
 110      }
 111  
 112      /**
 113       * @internal
 114       */
 115      public function serialize()
 116      {
 117          if (null === $this->exists) {
 118              $this->isFresh(0);
 119          }
 120  
 121          return serialize([$this->resource, $this->exists]);
 122      }
 123  
 124      /**
 125       * @internal
 126       */
 127      public function unserialize($serialized)
 128      {
 129          list($this->resource, $this->exists) = unserialize($serialized);
 130  
 131          if (\is_bool($this->exists)) {
 132              $this->exists = [$this->exists, null];
 133          }
 134      }
 135  
 136      /**
 137       * Throws a reflection exception when the passed class does not exist but is required.
 138       *
 139       * A class is considered "not required" when it's loaded as part of a "class_exists" or similar check.
 140       *
 141       * This function can be used as an autoload function to throw a reflection
 142       * exception if the class was not found by previous autoload functions.
 143       *
 144       * A previous exception can be passed. In this case, the class is considered as being
 145       * required totally, so if it doesn't exist, a reflection exception is always thrown.
 146       * If it exists, the previous exception is rethrown.
 147       *
 148       * @throws \ReflectionException
 149       *
 150       * @internal
 151       */
 152      public static function throwOnRequiredClass($class, \Exception $previous = null)
 153      {
 154          // If the passed class is the resource being checked, we shouldn't throw.
 155          if (null === $previous && self::$autoloadedClass === $class) {
 156              return;
 157          }
 158  
 159          if (class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false)) {
 160              if (null !== $previous) {
 161                  throw $previous;
 162              }
 163  
 164              return;
 165          }
 166  
 167          if ($previous instanceof \ReflectionException) {
 168              throw $previous;
 169          }
 170  
 171          $message = sprintf('Class "%s" not found.', $class);
 172  
 173          if (self::$autoloadedClass !== $class) {
 174              $message = substr_replace($message, sprintf(' while loading "%s"', self::$autoloadedClass), -1, 0);
 175          }
 176  
 177          if (null !== $previous) {
 178              $message = $previous->getMessage();
 179          }
 180  
 181          $e = new \ReflectionException($message, 0, $previous);
 182  
 183          if (null !== $previous) {
 184              throw $e;
 185          }
 186  
 187          $trace = debug_backtrace();
 188          $autoloadFrame = [
 189              'function' => 'spl_autoload_call',
 190              'args' => [$class],
 191          ];
 192  
 193          if (\PHP_VERSION_ID >= 80000 && isset($trace[1])) {
 194              $callerFrame = $trace[1];
 195              $i = 2;
 196          } elseif (false !== $i = array_search($autoloadFrame, $trace, true)) {
 197              $callerFrame = $trace[++$i];
 198          } else {
 199              throw $e;
 200          }
 201  
 202          if (isset($callerFrame['function']) && !isset($callerFrame['class'])) {
 203              switch ($callerFrame['function']) {
 204                  case 'get_class_methods':
 205                  case 'get_class_vars':
 206                  case 'get_parent_class':
 207                  case 'is_a':
 208                  case 'is_subclass_of':
 209                  case 'class_exists':
 210                  case 'class_implements':
 211                  case 'class_parents':
 212                  case 'trait_exists':
 213                  case 'defined':
 214                  case 'interface_exists':
 215                  case 'method_exists':
 216                  case 'property_exists':
 217                  case 'is_callable':
 218                      return;
 219              }
 220  
 221              $props = [
 222                  'file' => isset($callerFrame['file']) ? $callerFrame['file'] : null,
 223                  'line' => isset($callerFrame['line']) ? $callerFrame['line'] : null,
 224                  'trace' => \array_slice($trace, 1 + $i),
 225              ];
 226  
 227              foreach ($props as $p => $v) {
 228                  if (null !== $v) {
 229                      $r = new \ReflectionProperty('Exception', $p);
 230                      $r->setAccessible(true);
 231                      $r->setValue($e, $v);
 232                  }
 233              }
 234          }
 235  
 236          throw $e;
 237      }
 238  }


Generated: Mon Nov 25 19:05:08 2024 Cross-referenced by PHPXref 0.7.1