ReflectionManager.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * This file is part of Hyperf.
  5. *
  6. * @link https://www.hyperf.io
  7. * @document https://hyperf.wiki
  8. * @contact group@hyperf.io
  9. * @license https://github.com/hyperf/hyperf/blob/master/LICENSE
  10. */
  11. namespace Hyperf\Di;
  12. use Hyperf\Di\Aop\Ast;
  13. use InvalidArgumentException;
  14. use ReflectionClass;
  15. use ReflectionMethod;
  16. use ReflectionProperty;
  17. use Symfony\Component\Finder\Finder;
  18. use Throwable;
  19. use function Hyperf\Support\value;
  20. class ReflectionManager extends MetadataCollector
  21. {
  22. protected static array $container = [];
  23. public static function reflectClass(string $className): ReflectionClass
  24. {
  25. if (! isset(static::$container['class'][$className])) {
  26. if (! class_exists($className) && ! interface_exists($className) && ! trait_exists($className)) {
  27. throw new InvalidArgumentException("Class {$className} not exist");
  28. }
  29. static::$container['class'][$className] = new ReflectionClass($className);
  30. }
  31. return static::$container['class'][$className];
  32. }
  33. public static function reflectMethod(string $className, string $method): ReflectionMethod
  34. {
  35. $key = $className . '::' . $method;
  36. if (! isset(static::$container['method'][$key])) {
  37. // TODO check interface_exist
  38. if (! class_exists($className) && ! trait_exists($className)) {
  39. throw new InvalidArgumentException("Class {$className} not exist");
  40. }
  41. static::$container['method'][$key] = static::reflectClass($className)->getMethod($method);
  42. }
  43. return static::$container['method'][$key];
  44. }
  45. public static function reflectProperty(string $className, string $property): ReflectionProperty
  46. {
  47. $key = $className . '::' . $property;
  48. if (! isset(static::$container['property'][$key])) {
  49. if (! class_exists($className)) {
  50. throw new InvalidArgumentException("Class {$className} not exist");
  51. }
  52. static::$container['property'][$key] = static::reflectClass($className)->getProperty($property);
  53. }
  54. return static::$container['property'][$key];
  55. }
  56. public static function reflectPropertyNames(string $className)
  57. {
  58. $key = $className;
  59. if (! isset(static::$container['property_names'][$key])) {
  60. if (! class_exists($className) && ! interface_exists($className) && ! trait_exists($className)) {
  61. throw new InvalidArgumentException("Class {$className} not exist");
  62. }
  63. static::$container['property_names'][$key] = value(function () use ($className) {
  64. $properties = static::reflectClass($className)->getProperties();
  65. $result = [];
  66. foreach ($properties as $property) {
  67. $result[] = $property->getName();
  68. }
  69. return $result;
  70. });
  71. }
  72. return static::$container['property_names'][$key];
  73. }
  74. public static function clear(?string $key = null): void
  75. {
  76. if ($key === null) {
  77. static::$container = [];
  78. }
  79. }
  80. public static function getPropertyDefaultValue(ReflectionProperty $property)
  81. {
  82. return method_exists($property, 'getDefaultValue')
  83. ? $property->getDefaultValue()
  84. : $property->getDeclaringClass()->getDefaultProperties()[$property->getName()] ?? null;
  85. }
  86. public static function getAllClasses(array $paths): array
  87. {
  88. $finder = new Finder();
  89. $finder->files()->in($paths)->name('*.php');
  90. return static::getAllClassesByFinder($finder);
  91. }
  92. public static function getAllClassesByFinder(Finder $finder): array
  93. {
  94. $parser = new Ast();
  95. $reflectionClasses = [];
  96. foreach ($finder as $file) {
  97. try {
  98. $stmts = $parser->parse($file->getContents());
  99. if (! $className = $parser->parseClassByStmts($stmts)) {
  100. continue;
  101. }
  102. $reflectionClasses[$className] = static::reflectClass($className);
  103. } catch (Throwable $e) {
  104. echo sprintf(
  105. "\033[31m%s\033[0m",
  106. '[ERROR] DI Reflection Manager collecting class reflections failed. ' . PHP_EOL .
  107. "File: {$file->getRealPath()}." . PHP_EOL .
  108. 'Exception: ' . $e->getMessage()
  109. ) . PHP_EOL;
  110. }
  111. }
  112. return $reflectionClasses;
  113. }
  114. public static function getContainer(): array
  115. {
  116. return self::$container;
  117. }
  118. }