AnnotationReader.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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\Annotation;
  12. use Hyperf\Di\Exception\NotFoundException;
  13. use ReflectionClass;
  14. use ReflectionClassConstant;
  15. use ReflectionMethod;
  16. use ReflectionProperty;
  17. use Reflector;
  18. /**
  19. * A reader for docblock annotations.
  20. */
  21. class AnnotationReader
  22. {
  23. public function __construct(protected array $ignoreAnnotations = [])
  24. {
  25. }
  26. public function getClassAnnotations(ReflectionClass $class)
  27. {
  28. return $this->getAttributes($class);
  29. }
  30. public function getClassAnnotation(ReflectionClass $class, $annotationName)
  31. {
  32. $annotations = $this->getClassAnnotations($class);
  33. foreach ($annotations as $annotation) {
  34. if ($annotation instanceof $annotationName) {
  35. return $annotation;
  36. }
  37. }
  38. return null;
  39. }
  40. public function getPropertyAnnotations(ReflectionProperty $property)
  41. {
  42. return $this->getAttributes($property);
  43. }
  44. public function getPropertyAnnotation(ReflectionProperty $property, $annotationName)
  45. {
  46. $annotations = $this->getPropertyAnnotations($property);
  47. foreach ($annotations as $annotation) {
  48. if ($annotation instanceof $annotationName) {
  49. return $annotation;
  50. }
  51. }
  52. return null;
  53. }
  54. public function getMethodAnnotations(ReflectionMethod $method)
  55. {
  56. return $this->getAttributes($method);
  57. }
  58. public function getMethodAnnotation(ReflectionMethod $method, $annotationName)
  59. {
  60. $annotations = $this->getMethodAnnotations($method);
  61. foreach ($annotations as $annotation) {
  62. if ($annotation instanceof $annotationName) {
  63. return $annotation;
  64. }
  65. }
  66. return null;
  67. }
  68. public function getAttributes(Reflector $reflection): array
  69. {
  70. $result = [];
  71. if (! method_exists($reflection, 'getAttributes')) {
  72. return $result;
  73. }
  74. $attributes = $reflection->getAttributes();
  75. foreach ($attributes as $attribute) {
  76. if (in_array($attribute->getName(), $this->ignoreAnnotations, true)) {
  77. continue;
  78. }
  79. if (! class_exists($attribute->getName())) {
  80. $className = $methodName = $propertyName = $classConstantName = '';
  81. if ($reflection instanceof ReflectionClass) {
  82. $className = $reflection->getName();
  83. } elseif ($reflection instanceof ReflectionMethod) {
  84. $className = $reflection->getDeclaringClass()->getName();
  85. $methodName = $reflection->getName();
  86. } elseif ($reflection instanceof ReflectionProperty) {
  87. $className = $reflection->getDeclaringClass()->getName();
  88. $propertyName = $reflection->getName();
  89. } elseif ($reflection instanceof ReflectionClassConstant) {
  90. $className = $reflection->getDeclaringClass()->getName();
  91. $classConstantName = $reflection->getName();
  92. }
  93. $message = sprintf(
  94. "No attribute class found for '%s' in %s",
  95. $attribute->getName(),
  96. $className
  97. );
  98. if ($methodName) {
  99. $message .= sprintf('->%s() method', $methodName);
  100. }
  101. if ($propertyName) {
  102. $message .= sprintf('::$%s property', $propertyName);
  103. }
  104. if ($classConstantName) {
  105. $message .= sprintf('::%s class constant', $classConstantName);
  106. }
  107. throw new NotFoundException($message);
  108. }
  109. $result[] = $attribute->newInstance();
  110. }
  111. return $result;
  112. }
  113. }