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

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 as LegacyServiceSubscriberInterface;
  12. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  13. use Symfony\Component\Messenger\Handler\MessageSubscriberInterface;
  14. use Symfony\Contracts\Service\ServiceSubscriberInterface;
  15. /**
  16.  * @author Nicolas Grekas <p@tchwork.com>
  17.  */
  18. class ReflectionClassResource implements SelfCheckingResourceInterface, \Serializable {
  19.     private $files = [];
  20.     private $className;
  21.     private $classReflector;
  22.     private $excludedVendors = [];
  23.     private $hash;
  24.     public function __construct(\ReflectionClass $classReflector, array $excludedVendors = []) {
  25.         $this->className $classReflector->name;
  26.         $this->classReflector $classReflector;
  27.         $this->excludedVendors $excludedVendors;
  28.     }
  29.     public function isFresh($timestamp) {
  30.         if (null === $this->hash) {
  31.             $this->hash $this->computeHash();
  32.             $this->loadFiles($this->classReflector);
  33.         }
  34.         foreach ($this->files as $file => $v) {
  35.             if (false === $filemtime = @filemtime($file)) {
  36.                 return false;
  37.             }
  38.             if ($filemtime $timestamp) {
  39.                 return $this->hash === $this->computeHash();
  40.             }
  41.         }
  42.         return true;
  43.     }
  44.     public function __toString() {
  45.         return 'reflection.' $this->className;
  46.     }
  47.     /**
  48.      * @internal
  49.      */
  50.     public function serialize() {
  51.         if (null === $this->hash) {
  52.             $this->hash $this->computeHash();
  53.             $this->loadFiles($this->classReflector);
  54.         }
  55.         return serialize([$this->files$this->className$this->hash]);
  56.     }
  57.     /**
  58.      * @internal
  59.      */
  60.     public function unserialize($serialized) {
  61.         list($this->files$this->className$this->hash) = unserialize($serialized);
  62.     }
  63.     private function loadFiles(\ReflectionClass $class) {
  64.         foreach ($class->getInterfaces() as $v) {
  65.             $this->loadFiles($v);
  66.         }
  67.         do {
  68.             $file $class->getFileName();
  69.             if (false !== $file && file_exists($file)) {
  70.                 foreach ($this->excludedVendors as $vendor) {
  71.                     if (=== strpos($file$vendor) && false !== strpbrk(substr($file, \strlen($vendor), 1), '/' . \DIRECTORY_SEPARATOR)) {
  72.                         $file false;
  73.                         break;
  74.                     }
  75.                 }
  76.                 if ($file) {
  77.                     $this->files[$file] = null;
  78.                 }
  79.             }
  80.             foreach ($class->getTraits() as $v) {
  81.                 $this->loadFiles($v);
  82.             }
  83.         } while ($class $class->getParentClass());
  84.     }
  85.     private function computeHash() {
  86.         if (null === $this->classReflector) {
  87.             try {
  88.                 $this->classReflector = new \ReflectionClass($this->className);
  89.             } catch (\ReflectionException $e) {
  90.                 // the class does not exist anymore
  91.                 return false;
  92.             }
  93.         }
  94.         $hash hash_init('md5');
  95.         foreach ($this->generateSignature($this->classReflector) as $info) {
  96.             hash_update($hash$info);
  97.         }
  98.         return hash_final($hash);
  99.     }
  100.     private function generateSignature(\ReflectionClass $class) {
  101.         yield $class->getDocComment();
  102.         yield (int) $class->isFinal();
  103.         yield (int) $class->isAbstract();
  104.         if ($class->isTrait()) {
  105.             yield print_r(class_uses($class->name), true);
  106.         } else {
  107.             yield print_r(class_parents($class->name), true);
  108.             yield print_r(class_implements($class->name), true);
  109.             yield print_r($class->getConstants(), true);
  110.         }
  111.         if (!$class->isInterface()) {
  112.             $defaults $class->getDefaultProperties();
  113.             foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED) as $p) {
  114.                 yield $p->getDocComment() . $p;
  115.                 yield print_r(isset($defaults[$p->name]) ? $defaults[$p->name] : nulltrue);
  116.             }
  117.         }
  118.         foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $m) {
  119.             yield preg_replace('/^  @@.*/m'''$m);
  120.             $defaults = [];
  121.             foreach ($m->getParameters() as $p) {
  122.                 $defaults[$p->name] = $p->isDefaultValueAvailable() ? $p->getDefaultValue() : null;
  123.             }
  124.             yield print_r($defaultstrue);
  125.         }
  126.         if ($class->isAbstract() || $class->isInterface() || $class->isTrait()) {
  127.             return;
  128.         }
  129.         if (interface_exists(EventSubscriberInterface::class, false) && $class->isSubclassOf(EventSubscriberInterface::class)) {
  130.             yield EventSubscriberInterface::class;
  131.             yield print_r($class->name::getSubscribedEvents(), true);
  132.         }
  133.         if (interface_exists(MessageSubscriberInterface::class, false) && $class->isSubclassOf(MessageSubscriberInterface::class)) {
  134.             yield MessageSubscriberInterface::class;
  135.             foreach ($class->name::getHandledMessages() as $key => $value) {
  136.                 yield $key print_r($valuetrue);
  137.             }
  138.         }
  139.         if (interface_exists(LegacyServiceSubscriberInterface::class, false) && $class->isSubclassOf(LegacyServiceSubscriberInterface::class)) {
  140.             yield LegacyServiceSubscriberInterface::class;
  141.             yield print_r([$class->name'getSubscribedServices'](), true);
  142.         } elseif (interface_exists(ServiceSubscriberInterface::class, false) && $class->isSubclassOf(ServiceSubscriberInterface::class)) {
  143.             yield ServiceSubscriberInterface::class;
  144.             yield print_r($class->name::getSubscribedServices(), true);
  145.         }
  146.     }
  147. }