[ Index ] |
PHP Cross Reference of phpBB-3.3.14-deutsch |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 25 19:05:08 2024 | Cross-referenced by PHPXref 0.7.1 |