9a1d7ba57b2caaea6f9f0ec54756af74c145c697
[yaffs-website] / vendor / symfony / config / Resource / ClassExistenceResource.php
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 = array();
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;
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[(int) (0 >= $timestamp)][$this->resource]) {
69             $exists = $exists || $loaded;
70         } elseif (!$exists = $loaded) {
71             if (!self::$autoloadLevel++) {
72                 spl_autoload_register(__CLASS__.'::throwOnRequiredClass');
73             }
74             $autoloadedClass = self::$autoloadedClass;
75             self::$autoloadedClass = $this->resource;
76
77             try {
78                 $exists = class_exists($this->resource) || interface_exists($this->resource, false) || trait_exists($this->resource, false);
79             } catch (\ReflectionException $e) {
80                 if (0 >= $timestamp) {
81                     unset(self::$existsCache[1][$this->resource]);
82                     throw $e;
83                 }
84             } finally {
85                 self::$autoloadedClass = $autoloadedClass;
86                 if (!--self::$autoloadLevel) {
87                     spl_autoload_unregister(__CLASS__.'::throwOnRequiredClass');
88                 }
89             }
90         }
91
92         if (null === $this->exists) {
93             $this->exists = $exists;
94         }
95
96         return $this->exists xor !$exists;
97     }
98
99     /**
100      * {@inheritdoc}
101      */
102     public function serialize()
103     {
104         if (null === $this->exists) {
105             $this->isFresh(0);
106         }
107
108         return serialize(array($this->resource, $this->exists));
109     }
110
111     /**
112      * {@inheritdoc}
113      */
114     public function unserialize($serialized)
115     {
116         list($this->resource, $this->exists) = unserialize($serialized);
117     }
118
119     /**
120      * @throws \ReflectionException When $class is not found and is required
121      */
122     private static function throwOnRequiredClass($class)
123     {
124         if (self::$autoloadedClass === $class) {
125             return;
126         }
127         $e = new \ReflectionException("Class $class not found");
128         $trace = $e->getTrace();
129         $autoloadFrame = array(
130             'function' => 'spl_autoload_call',
131             'args' => array($class),
132         );
133         $i = 1 + array_search($autoloadFrame, $trace, true);
134
135         if (isset($trace[$i]['function']) && !isset($trace[$i]['class'])) {
136             switch ($trace[$i]['function']) {
137                 case 'get_class_methods':
138                 case 'get_class_vars':
139                 case 'get_parent_class':
140                 case 'is_a':
141                 case 'is_subclass_of':
142                 case 'class_exists':
143                 case 'class_implements':
144                 case 'class_parents':
145                 case 'trait_exists':
146                 case 'defined':
147                 case 'interface_exists':
148                 case 'method_exists':
149                 case 'property_exists':
150                 case 'is_callable':
151                     return;
152             }
153
154             $props = array(
155                 'file' => $trace[$i]['file'],
156                 'line' => $trace[$i]['line'],
157                 'trace' => \array_slice($trace, 1 + $i),
158             );
159
160             foreach ($props as $p => $v) {
161                 $r = new \ReflectionProperty('Exception', $p);
162                 $r->setAccessible(true);
163                 $r->setValue($e, $v);
164             }
165         }
166
167         throw $e;
168     }
169 }