1: <?php
2:
3: declare(strict_types=1);
4:
5: namespace PHPStan\BetterReflection\Reflection\Adapter;
6:
7: use OutOfBoundsException;
8: use PhpParser\Node\Expr;
9: use ReflectionClassConstant as CoreReflectionClassConstant;
10: use ReturnTypeWillChange;
11: use PHPStan\BetterReflection\Reflection\ReflectionAttribute as BetterReflectionAttribute;
12: use PHPStan\BetterReflection\Reflection\ReflectionClassConstant as BetterReflectionClassConstant;
13: use PHPStan\BetterReflection\Reflection\ReflectionEnumCase as BetterReflectionEnumCase;
14: use ValueError;
15:
16: use function array_map;
17: use function constant;
18: use function sprintf;
19:
20: final class ReflectionClassConstant extends CoreReflectionClassConstant
21: {
22: public const IS_PUBLIC = 1;
23:
24: public const IS_PROTECTED = 2;
25:
26: public const IS_PRIVATE = 4;
27:
28: public const IS_FINAL = 32;
29: /**
30: * @var BetterReflectionClassConstant|BetterReflectionEnumCase
31: */
32: private $betterClassConstantOrEnumCase;
33:
34: /**
35: * @param BetterReflectionClassConstant|BetterReflectionEnumCase $betterClassConstantOrEnumCase
36: */
37: public function __construct($betterClassConstantOrEnumCase)
38: {
39: $this->betterClassConstantOrEnumCase = $betterClassConstantOrEnumCase;
40: unset($this->name);
41: unset($this->class);
42: }
43:
44: /**
45: * Get the name of the reflection (e.g. if this is a ReflectionClass this
46: * will be the class name).
47: */
48: public function getName(): string
49: {
50: return $this->betterClassConstantOrEnumCase->getName();
51: }
52:
53:
54: /**
55: * @deprecated Use getValueExpression()
56: */
57: #[ReturnTypeWillChange]
58: public function getValue()
59: {
60: if ($this->betterClassConstantOrEnumCase instanceof BetterReflectionEnumCase) {
61: throw new Exception\NotImplemented('Not implemented');
62: }
63:
64: return $this->betterClassConstantOrEnumCase->getValue();
65: }
66:
67: /**
68: * @deprecated Use getValueExpression()
69: */
70: public function getValueExpr(): Expr
71: {
72: return $this->getValueExpression();
73: }
74:
75: public function getValueExpression(): Expr
76: {
77: return $this->betterClassConstantOrEnumCase->getValueExpression();
78: }
79:
80: /**
81: * Constant is public
82: */
83: public function isPublic(): bool
84: {
85: if ($this->betterClassConstantOrEnumCase instanceof BetterReflectionEnumCase) {
86: return true;
87: }
88:
89: return $this->betterClassConstantOrEnumCase->isPublic();
90: }
91:
92: /**
93: * Constant is private
94: */
95: public function isPrivate(): bool
96: {
97: if ($this->betterClassConstantOrEnumCase instanceof BetterReflectionEnumCase) {
98: return false;
99: }
100:
101: return $this->betterClassConstantOrEnumCase->isPrivate();
102: }
103:
104: /**
105: * Constant is protected
106: */
107: public function isProtected(): bool
108: {
109: if ($this->betterClassConstantOrEnumCase instanceof BetterReflectionEnumCase) {
110: return false;
111: }
112:
113: return $this->betterClassConstantOrEnumCase->isProtected();
114: }
115:
116: /**
117: * Returns a bitfield of the access modifiers for this constant
118: */
119: public function getModifiers(): int
120: {
121: if ($this->betterClassConstantOrEnumCase instanceof BetterReflectionEnumCase) {
122: return ReflectionClassConstant::IS_PUBLIC;
123: }
124:
125: return $this->betterClassConstantOrEnumCase->getModifiers();
126: }
127:
128: /**
129: * Get the declaring class
130: */
131: public function getDeclaringClass(): ReflectionClass
132: {
133: if ($this->betterClassConstantOrEnumCase instanceof BetterReflectionEnumCase) {
134: return new ReflectionClass($this->betterClassConstantOrEnumCase->getDeclaringClass());
135: }
136:
137: return new ReflectionClass($this->betterClassConstantOrEnumCase->getImplementingClass());
138: }
139:
140: /**
141: * Returns the doc comment for this constant
142: *
143: * @return string|false
144: */
145: #[ReturnTypeWillChange]
146: public function getDocComment()
147: {
148: return $this->betterClassConstantOrEnumCase->getDocComment() ?? false;
149: }
150:
151: /**
152: * To string
153: *
154: * @link https://php.net/manual/en/reflector.tostring.php
155: */
156: public function __toString(): string
157: {
158: return $this->betterClassConstantOrEnumCase->__toString();
159: }
160:
161: /**
162: * @param class-string|null $name
163: *
164: * @return list<ReflectionAttribute|FakeReflectionAttribute>
165: */
166: public function getAttributes(?string $name = null, int $flags = 0): array
167: {
168: if ($flags !== 0 && $flags !== ReflectionAttribute::IS_INSTANCEOF) {
169: throw new ValueError('Argument #2 ($flags) must be a valid attribute filter flag');
170: }
171:
172: if ($name !== null && $flags !== 0) {
173: $attributes = $this->betterClassConstantOrEnumCase->getAttributesByInstance($name);
174: } elseif ($name !== null) {
175: $attributes = $this->betterClassConstantOrEnumCase->getAttributesByName($name);
176: } else {
177: $attributes = $this->betterClassConstantOrEnumCase->getAttributes();
178: }
179:
180: return array_map(static function (BetterReflectionAttribute $betterReflectionAttribute) {
181: return ReflectionAttributeFactory::create($betterReflectionAttribute);
182: }, $attributes);
183: }
184:
185: public function isFinal(): bool
186: {
187: if ($this->betterClassConstantOrEnumCase instanceof BetterReflectionEnumCase) {
188: return true;
189: }
190:
191: return $this->betterClassConstantOrEnumCase->isFinal();
192: }
193:
194: public function isEnumCase(): bool
195: {
196: return $this->betterClassConstantOrEnumCase instanceof BetterReflectionEnumCase;
197: }
198:
199: /**
200: * @return mixed
201: */
202: public function __get(string $name)
203: {
204: if ($name === 'name') {
205: return $this->betterClassConstantOrEnumCase->getName();
206: }
207:
208: if ($name === 'class') {
209: return $this->getDeclaringClass()->getName();
210: }
211:
212: throw new OutOfBoundsException(sprintf('Property %s::$%s does not exist.', self::class, $name));
213: }
214: }
215: