X-Git-Url: http://www.aleph1.co.uk/gitweb/?a=blobdiff_plain;ds=sidebyside;f=vendor%2Fsymfony%2Fconfig%2FResource%2FClassExistenceResource.php;fp=vendor%2Fsymfony%2Fconfig%2FResource%2FClassExistenceResource.php;h=e3fd095b6008dd2193050b8b3c387bda4c9a0518;hb=af6d1fb995500ae68849458ee10d66abbdcfb252;hp=8a9df906a643d8fca931a3ae2feabdf16f66b6a9;hpb=680c79a86e3ed402f263faeac92e89fb6d9edcc0;p=yaffs-website diff --git a/vendor/symfony/config/Resource/ClassExistenceResource.php b/vendor/symfony/config/Resource/ClassExistenceResource.php index 8a9df906a..e3fd095b6 100644 --- a/vendor/symfony/config/Resource/ClassExistenceResource.php +++ b/vendor/symfony/config/Resource/ClassExistenceResource.php @@ -24,13 +24,20 @@ class ClassExistenceResource implements SelfCheckingResourceInterface, \Serializ private $resource; private $exists; + private static $autoloadLevel = 0; + private static $autoloadedClass; + private static $existsCache = array(); + /** - * @param string $resource The fully-qualified class name + * @param string $resource The fully-qualified class name + * @param bool|null $exists Boolean when the existency check has already been done */ - public function __construct($resource) + public function __construct($resource, $exists = null) { $this->resource = $resource; - $this->exists = class_exists($resource); + if (null !== $exists) { + $this->exists = (bool) $exists; + } } /** @@ -51,10 +58,42 @@ class ClassExistenceResource implements SelfCheckingResourceInterface, \Serializ /** * {@inheritdoc} + * + * @throws \ReflectionException when a parent class/interface/trait is not found */ public function isFresh($timestamp) { - return class_exists($this->resource) === $this->exists; + $loaded = class_exists($this->resource, false) || interface_exists($this->resource, false) || trait_exists($this->resource, false); + + if (null !== $exists = &self::$existsCache[(int) (0 >= $timestamp)][$this->resource]) { + $exists = $exists || $loaded; + } elseif (!$exists = $loaded) { + if (!self::$autoloadLevel++) { + spl_autoload_register(__CLASS__.'::throwOnRequiredClass'); + } + $autoloadedClass = self::$autoloadedClass; + self::$autoloadedClass = $this->resource; + + try { + $exists = class_exists($this->resource) || interface_exists($this->resource, false) || trait_exists($this->resource, false); + } catch (\ReflectionException $e) { + if (0 >= $timestamp) { + unset(self::$existsCache[1][$this->resource]); + throw $e; + } + } finally { + self::$autoloadedClass = $autoloadedClass; + if (!--self::$autoloadLevel) { + spl_autoload_unregister(__CLASS__.'::throwOnRequiredClass'); + } + } + } + + if (null === $this->exists) { + $this->exists = $exists; + } + + return $this->exists xor !$exists; } /** @@ -62,6 +101,10 @@ class ClassExistenceResource implements SelfCheckingResourceInterface, \Serializ */ public function serialize() { + if (null === $this->exists) { + $this->isFresh(0); + } + return serialize(array($this->resource, $this->exists)); } @@ -72,4 +115,55 @@ class ClassExistenceResource implements SelfCheckingResourceInterface, \Serializ { list($this->resource, $this->exists) = unserialize($serialized); } + + /** + * @throws \ReflectionException When $class is not found and is required + */ + private static function throwOnRequiredClass($class) + { + if (self::$autoloadedClass === $class) { + return; + } + $e = new \ReflectionException("Class $class not found"); + $trace = $e->getTrace(); + $autoloadFrame = array( + 'function' => 'spl_autoload_call', + 'args' => array($class), + ); + $i = 1 + array_search($autoloadFrame, $trace, true); + + if (isset($trace[$i]['function']) && !isset($trace[$i]['class'])) { + switch ($trace[$i]['function']) { + case 'get_class_methods': + case 'get_class_vars': + case 'get_parent_class': + case 'is_a': + case 'is_subclass_of': + case 'class_exists': + case 'class_implements': + case 'class_parents': + case 'trait_exists': + case 'defined': + case 'interface_exists': + case 'method_exists': + case 'property_exists': + case 'is_callable': + return; + } + + $props = array( + 'file' => $trace[$i]['file'], + 'line' => $trace[$i]['line'], + 'trace' => array_slice($trace, 1 + $i), + ); + + foreach ($props as $p => $v) { + $r = new \ReflectionProperty('Exception', $p); + $r->setAccessible(true); + $r->setValue($e, $v); + } + } + + throw $e; + } }