65156a06de779a0ffaaa4634659ea15b7e1c0dbe
[yaffs-website] / vendor / symfony / config / Resource / ReflectionClassResource.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 use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
15 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
16
17 /**
18  * @author Nicolas Grekas <p@tchwork.com>
19  */
20 class ReflectionClassResource implements SelfCheckingResourceInterface, \Serializable
21 {
22     private $files = array();
23     private $className;
24     private $classReflector;
25     private $excludedVendors = array();
26     private $hash;
27
28     public function __construct(\ReflectionClass $classReflector, $excludedVendors = array())
29     {
30         $this->className = $classReflector->name;
31         $this->classReflector = $classReflector;
32         $this->excludedVendors = $excludedVendors;
33     }
34
35     public function isFresh($timestamp)
36     {
37         if (null === $this->hash) {
38             $this->hash = $this->computeHash();
39             $this->loadFiles($this->classReflector);
40         }
41
42         foreach ($this->files as $file => $v) {
43             if (false === $filemtime = @filemtime($file)) {
44                 return false;
45             }
46
47             if ($filemtime > $timestamp) {
48                 return $this->hash === $this->computeHash();
49             }
50         }
51
52         return true;
53     }
54
55     public function __toString()
56     {
57         return 'reflection.'.$this->className;
58     }
59
60     public function serialize()
61     {
62         if (null === $this->hash) {
63             $this->hash = $this->computeHash();
64             $this->loadFiles($this->classReflector);
65         }
66
67         return serialize(array($this->files, $this->className, $this->hash));
68     }
69
70     public function unserialize($serialized)
71     {
72         list($this->files, $this->className, $this->hash) = unserialize($serialized);
73     }
74
75     private function loadFiles(\ReflectionClass $class)
76     {
77         foreach ($class->getInterfaces() as $v) {
78             $this->loadFiles($v);
79         }
80         do {
81             $file = $class->getFileName();
82             if (false !== $file && file_exists($file)) {
83                 foreach ($this->excludedVendors as $vendor) {
84                     if (0 === strpos($file, $vendor) && false !== strpbrk(substr($file, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) {
85                         $file = false;
86                         break;
87                     }
88                 }
89                 if ($file) {
90                     $this->files[$file] = null;
91                 }
92             }
93             foreach ($class->getTraits() as $v) {
94                 $this->loadFiles($v);
95             }
96         } while ($class = $class->getParentClass());
97     }
98
99     private function computeHash()
100     {
101         if (null === $this->classReflector) {
102             try {
103                 $this->classReflector = new \ReflectionClass($this->className);
104             } catch (\ReflectionException $e) {
105                 // the class does not exist anymore
106                 return false;
107             }
108         }
109         $hash = hash_init('md5');
110
111         foreach ($this->generateSignature($this->classReflector) as $info) {
112             hash_update($hash, $info);
113         }
114
115         return hash_final($hash);
116     }
117
118     private function generateSignature(\ReflectionClass $class)
119     {
120         yield $class->getDocComment();
121         yield (int) $class->isFinal();
122         yield (int) $class->isAbstract();
123
124         if ($class->isTrait()) {
125             yield print_r(class_uses($class->name), true);
126         } else {
127             yield print_r(class_parents($class->name), true);
128             yield print_r(class_implements($class->name), true);
129             yield print_r($class->getConstants(), true);
130         }
131
132         if (!$class->isInterface()) {
133             $defaults = $class->getDefaultProperties();
134
135             foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED) as $p) {
136                 yield $p->getDocComment().$p;
137                 yield print_r($defaults[$p->name], true);
138             }
139         }
140
141         if (\defined('HHVM_VERSION')) {
142             foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $m) {
143                 // workaround HHVM bug with variadics, see https://github.com/facebook/hhvm/issues/5762
144                 yield preg_replace('/^  @@.*/m', '', new ReflectionMethodHhvmWrapper($m->class, $m->name));
145             }
146         } else {
147             foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $m) {
148                 yield preg_replace('/^  @@.*/m', '', $m);
149
150                 $defaults = array();
151                 foreach ($m->getParameters() as $p) {
152                     $defaults[$p->name] = $p->isDefaultValueAvailable() ? $p->getDefaultValue() : null;
153                 }
154                 yield print_r($defaults, true);
155             }
156         }
157
158         if ($class->isAbstract() || $class->isInterface() || $class->isTrait()) {
159             return;
160         }
161
162         if (interface_exists(EventSubscriberInterface::class, false) && $class->isSubclassOf(EventSubscriberInterface::class)) {
163             yield EventSubscriberInterface::class;
164             yield print_r(\call_user_func(array($class->name, 'getSubscribedEvents')), true);
165         }
166
167         if (interface_exists(ServiceSubscriberInterface::class, false) && $class->isSubclassOf(ServiceSubscriberInterface::class)) {
168             yield ServiceSubscriberInterface::class;
169             yield print_r(\call_user_func(array($class->name, 'getSubscribedServices')), true);
170         }
171     }
172 }
173
174 /**
175  * @internal
176  */
177 class ReflectionMethodHhvmWrapper extends \ReflectionMethod
178 {
179     public function getParameters()
180     {
181         $params = array();
182
183         foreach (parent::getParameters() as $i => $p) {
184             $params[] = new ReflectionParameterHhvmWrapper(array($this->class, $this->name), $i);
185         }
186
187         return $params;
188     }
189 }
190
191 /**
192  * @internal
193  */
194 class ReflectionParameterHhvmWrapper extends \ReflectionParameter
195 {
196     public function getDefaultValue()
197     {
198         return array($this->isVariadic(), $this->isDefaultValueAvailable() ? parent::getDefaultValue() : null);
199     }
200 }