vendor/symfony/config/Resource/ReflectionClassResource.php line 20

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