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

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <[email protected]>
  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 <[email protected]>
  17.  *
  18.  * @final since Symfony 4.3
  19.  */
  20. class ReflectionClassResource implements SelfCheckingResourceInterface
  21. {
  22.     private $files = [];
  23.     private $className;
  24.     private $classReflector;
  25.     private $excludedVendors = [];
  26.     private $hash;
  27.     public function __construct(\ReflectionClass $classReflector, array $excludedVendors = [])
  28.     {
  29.         $this->className $classReflector->name;
  30.         $this->classReflector $classReflector;
  31.         $this->excludedVendors $excludedVendors;
  32.     }
  33.     public function isFresh($timestamp)
  34.     {
  35.         if (null === $this->hash) {
  36.             $this->hash $this->computeHash();
  37.             $this->loadFiles($this->classReflector);
  38.         }
  39.         foreach ($this->files as $file => $v) {
  40.             if (false === $filemtime = @filemtime($file)) {
  41.                 return false;
  42.             }
  43.             if ($filemtime $timestamp) {
  44.                 return $this->hash === $this->computeHash();
  45.             }
  46.         }
  47.         return true;
  48.     }
  49.     public function __toString()
  50.     {
  51.         return 'reflection.'.$this->className;
  52.     }
  53.     /**
  54.      * @internal
  55.      */
  56.     public function __sleep(): array
  57.     {
  58.         if (null === $this->hash) {
  59.             $this->hash $this->computeHash();
  60.             $this->loadFiles($this->classReflector);
  61.         }
  62.         return ['files''className''hash'];
  63.     }
  64.     private function loadFiles(\ReflectionClass $class)
  65.     {
  66.         foreach ($class->getInterfaces() as $v) {
  67.             $this->loadFiles($v);
  68.         }
  69.         do {
  70.             $file $class->getFileName();
  71.             if (false !== $file && file_exists($file)) {
  72.                 foreach ($this->excludedVendors as $vendor) {
  73.                     if (=== strpos($file$vendor) && false !== strpbrk(substr($file, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) {
  74.                         $file false;
  75.                         break;
  76.                     }
  77.                 }
  78.                 if ($file) {
  79.                     $this->files[$file] = null;
  80.                 }
  81.             }
  82.             foreach ($class->getTraits() as $v) {
  83.                 $this->loadFiles($v);
  84.             }
  85.         } while ($class $class->getParentClass());
  86.     }
  87.     private function computeHash(): string
  88.     {
  89.         if (null === $this->classReflector) {
  90.             try {
  91.                 $this->classReflector = new \ReflectionClass($this->className);
  92.             } catch (\ReflectionException $e) {
  93.                 // the class does not exist anymore
  94.                 return false;
  95.             }
  96.         }
  97.         $hash hash_init('md5');
  98.         foreach ($this->generateSignature($this->classReflector) as $info) {
  99.             hash_update($hash$info);
  100.         }
  101.         return hash_final($hash);
  102.     }
  103.     private function generateSignature(\ReflectionClass $class): iterable
  104.     {
  105.         yield $class->getDocComment();
  106.         yield (int) $class->isFinal();
  107.         yield (int) $class->isAbstract();
  108.         if ($class->isTrait()) {
  109.             yield print_r(class_uses($class->name), true);
  110.         } else {
  111.             yield print_r(class_parents($class->name), true);
  112.             yield print_r(class_implements($class->name), true);
  113.             yield print_r($class->getConstants(), true);
  114.         }
  115.         if (!$class->isInterface()) {
  116.             $defaults $class->getDefaultProperties();
  117.             foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED) as $p) {
  118.                 yield $p->getDocComment();
  119.                 yield $p->isDefault() ? '<default>' '';
  120.                 yield $p->isPublic() ? 'public' 'protected';
  121.                 yield $p->isStatic() ? 'static' '';
  122.                 yield '$'.$p->name;
  123.                 yield print_r(isset($defaults[$p->name]) && !\is_object($defaults[$p->name]) ? $defaults[$p->name] : nulltrue);
  124.             }
  125.         }
  126.         foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $m) {
  127.             $defaults = [];
  128.             $parametersWithUndefinedConstants = [];
  129.             foreach ($m->getParameters() as $p) {
  130.                 if (!$p->isDefaultValueAvailable()) {
  131.                     $defaults[$p->name] = null;
  132.                     continue;
  133.                 }
  134.                 if (!$p->isDefaultValueConstant() || \defined($p->getDefaultValueConstantName())) {
  135.                     $defaults[$p->name] = $p->getDefaultValue();
  136.                     continue;
  137.                 }
  138.                 $defaults[$p->name] = $p->getDefaultValueConstantName();
  139.                 $parametersWithUndefinedConstants[$p->name] = true;
  140.             }
  141.             if (!$parametersWithUndefinedConstants) {
  142.                 yield preg_replace('/^  @@.*/m'''$m);
  143.             } else {
  144.                 $t $m->getReturnType();
  145.                 $stack = [
  146.                     $m->getDocComment(),
  147.                     $m->getName(),
  148.                     $m->isAbstract(),
  149.                     $m->isFinal(),
  150.                     $m->isStatic(),
  151.                     $m->isPublic(),
  152.                     $m->isPrivate(),
  153.                     $m->isProtected(),
  154.                     $m->returnsReference(),
  155.                     $t instanceof \ReflectionNamedType ? ((string) $t->allowsNull()).$t->getName() : (string) $t,
  156.                 ];
  157.                 foreach ($m->getParameters() as $p) {
  158.                     if (!isset($parametersWithUndefinedConstants[$p->name])) {
  159.                         $stack[] = (string) $p;
  160.                     } else {
  161.                         $t $p->getType();
  162.                         $stack[] = $p->isOptional();
  163.                         $stack[] = $t instanceof \ReflectionNamedType ? ((string) $t->allowsNull()).$t->getName() : (string) $t;
  164.                         $stack[] = $p->isPassedByReference();
  165.                         $stack[] = $p->isVariadic();
  166.                         $stack[] = $p->getName();
  167.                     }
  168.                 }
  169.                 yield implode(','$stack);
  170.             }
  171.             yield print_r($defaultstrue);
  172.         }
  173.         if ($class->isAbstract() || $class->isInterface() || $class->isTrait()) {
  174.             return;
  175.         }
  176.         if (interface_exists(EventSubscriberInterface::class, false) && $class->isSubclassOf(EventSubscriberInterface::class)) {
  177.             yield EventSubscriberInterface::class;
  178.             yield print_r($class->name::getSubscribedEvents(), true);
  179.         }
  180.         if (interface_exists(MessageSubscriberInterface::class, false) && $class->isSubclassOf(MessageSubscriberInterface::class)) {
  181.             yield MessageSubscriberInterface::class;
  182.             foreach ($class->name::getHandledMessages() as $key => $value) {
  183.                 yield $key.print_r($valuetrue);
  184.             }
  185.         }
  186.         if (interface_exists(LegacyServiceSubscriberInterface::class, false) && $class->isSubclassOf(LegacyServiceSubscriberInterface::class)) {
  187.             yield LegacyServiceSubscriberInterface::class;
  188.             yield print_r([$class->name'getSubscribedServices'](), true);
  189.         } elseif (interface_exists(ServiceSubscriberInterface::class, false) && $class->isSubclassOf(ServiceSubscriberInterface::class)) {
  190.             yield ServiceSubscriberInterface::class;
  191.             yield print_r($class->name::getSubscribedServices(), true);
  192.         }
  193.     }
  194. }