| 1: | <?php | 
| 2: |  | 
| 3: | declare(strict_types=1); | 
| 4: |  | 
| 5: | namespace PHPStan\BetterReflection\Reflection\Adapter; | 
| 6: |  | 
| 7: | use ArgumentCountError; | 
| 8: | use OutOfBoundsException; | 
| 9: | use PhpParser\Node\Expr; | 
| 10: | use PropertyHookType; | 
| 11: | use ReflectionException as CoreReflectionException; | 
| 12: | use ReflectionMethod as CoreReflectionMethod; | 
| 13: | use ReflectionProperty as CoreReflectionProperty; | 
| 14: | use ReflectionType as CoreReflectionType; | 
| 15: | use ReturnTypeWillChange; | 
| 16: | use PHPStan\BetterReflection\Reflection\Exception\NoObjectProvided; | 
| 17: | use PHPStan\BetterReflection\Reflection\Exception\NotAnObject; | 
| 18: | use PHPStan\BetterReflection\Reflection\ReflectionAttribute as BetterReflectionAttribute; | 
| 19: | use PHPStan\BetterReflection\Reflection\ReflectionMethod as BetterReflectionMethod; | 
| 20: | use PHPStan\BetterReflection\Reflection\ReflectionProperty as BetterReflectionProperty; | 
| 21: | use PHPStan\BetterReflection\Reflection\ReflectionPropertyHookType as BetterReflectionPropertyHookType; | 
| 22: | use Throwable; | 
| 23: | use TypeError; | 
| 24: | use ValueError; | 
| 25: |  | 
| 26: | use function array_map; | 
| 27: | use function gettype; | 
| 28: | use function sprintf; | 
| 29: |  | 
| 30: |  | 
| 31: | final class ReflectionProperty extends CoreReflectionProperty | 
| 32: | { | 
| 33: | private BetterReflectionProperty $betterReflectionProperty; | 
| 34: |  | 
| 35: |  | 
| 36: |  | 
| 37: |  | 
| 38: |  | 
| 39: | public const IS_FINAL_COMPATIBILITY = 32; | 
| 40: |  | 
| 41: |  | 
| 42: |  | 
| 43: |  | 
| 44: |  | 
| 45: |  | 
| 46: | public const IS_ABSTRACT_COMPATIBILITY = 64; | 
| 47: |  | 
| 48: |  | 
| 49: |  | 
| 50: |  | 
| 51: |  | 
| 52: |  | 
| 53: | public const IS_VIRTUAL_COMPATIBILITY = 512; | 
| 54: |  | 
| 55: |  | 
| 56: |  | 
| 57: |  | 
| 58: |  | 
| 59: |  | 
| 60: | public const IS_PROTECTED_SET_COMPATIBILITY = 2048; | 
| 61: |  | 
| 62: |  | 
| 63: |  | 
| 64: |  | 
| 65: |  | 
| 66: |  | 
| 67: | public const IS_PRIVATE_SET_COMPATIBILITY = 4096; | 
| 68: |  | 
| 69: |  | 
| 70: | public const IS_READONLY_COMPATIBILITY = 128; | 
| 71: |  | 
| 72: | public function __construct(BetterReflectionProperty $betterReflectionProperty) | 
| 73: | { | 
| 74: | $this->betterReflectionProperty = $betterReflectionProperty; | 
| 75: | unset($this->name); | 
| 76: | unset($this->class); | 
| 77: | } | 
| 78: |  | 
| 79: |  | 
| 80: | public function __toString(): string | 
| 81: | { | 
| 82: | return $this->betterReflectionProperty->__toString(); | 
| 83: | } | 
| 84: |  | 
| 85: | public function getName(): string | 
| 86: | { | 
| 87: | return $this->betterReflectionProperty->getName(); | 
| 88: | } | 
| 89: |  | 
| 90: |  | 
| 91: |  | 
| 92: |  | 
| 93: |  | 
| 94: | #[ReturnTypeWillChange] | 
| 95: | public function getValue($object = null) | 
| 96: | { | 
| 97: | try { | 
| 98: | return $this->betterReflectionProperty->getValue($object); | 
| 99: | } catch (NoObjectProvided $exception) { | 
| 100: | return null; | 
| 101: | } catch (Throwable $e) { | 
| 102: | throw new CoreReflectionException($e->getMessage(), 0, $e); | 
| 103: | } | 
| 104: | } | 
| 105: |  | 
| 106: |  | 
| 107: |  | 
| 108: |  | 
| 109: | public function setValue($objectOrValue, $value = null): void | 
| 110: | { | 
| 111: | try { | 
| 112: | $this->betterReflectionProperty->setValue($objectOrValue, $value); | 
| 113: | } catch (NoObjectProvided $exception) { | 
| 114: | throw new ArgumentCountError('ReflectionProperty::setValue() expects exactly 2 arguments, 1 given'); | 
| 115: | } catch (NotAnObject $exception) { | 
| 116: | throw new TypeError(sprintf('ReflectionProperty::setValue(): Argument #1 ($objectOrValue) must be of type object, %s given', gettype($objectOrValue))); | 
| 117: | } catch (Throwable $e) { | 
| 118: | throw new CoreReflectionException($e->getMessage(), 0, $e); | 
| 119: | } | 
| 120: | } | 
| 121: |  | 
| 122: |  | 
| 123: |  | 
| 124: |  | 
| 125: | public function setRawValueWithoutLazyInitialization(object $object, $value): void | 
| 126: | { | 
| 127: | throw Exception\NotImplementedBecauseItTriggersAutoloading::create(); | 
| 128: | } | 
| 129: |  | 
| 130: |  | 
| 131: | public function isLazy(object $object): bool | 
| 132: | { | 
| 133: | throw Exception\NotImplementedBecauseItTriggersAutoloading::create(); | 
| 134: | } | 
| 135: |  | 
| 136: | public function skipLazyInitialization(object $object): void | 
| 137: | { | 
| 138: | throw Exception\NotImplementedBecauseItTriggersAutoloading::create(); | 
| 139: | } | 
| 140: |  | 
| 141: |  | 
| 142: | public function hasType(): bool | 
| 143: | { | 
| 144: | return $this->betterReflectionProperty->hasType(); | 
| 145: | } | 
| 146: |  | 
| 147: |  | 
| 148: |  | 
| 149: |  | 
| 150: | public function getType(): ?\ReflectionType | 
| 151: | { | 
| 152: | return ReflectionType::fromTypeOrNull($this->betterReflectionProperty->getType()); | 
| 153: | } | 
| 154: |  | 
| 155: | public function isPublic(): bool | 
| 156: | { | 
| 157: | return $this->betterReflectionProperty->isPublic(); | 
| 158: | } | 
| 159: |  | 
| 160: | public function isPrivate(): bool | 
| 161: | { | 
| 162: | return $this->betterReflectionProperty->isPrivate(); | 
| 163: | } | 
| 164: |  | 
| 165: |  | 
| 166: | public function isPrivateSet(): bool | 
| 167: | { | 
| 168: | return $this->betterReflectionProperty->isPrivateSet(); | 
| 169: | } | 
| 170: |  | 
| 171: |  | 
| 172: | public function isProtected(): bool | 
| 173: | { | 
| 174: | return $this->betterReflectionProperty->isProtected(); | 
| 175: | } | 
| 176: |  | 
| 177: |  | 
| 178: | public function isProtectedSet(): bool | 
| 179: | { | 
| 180: | return $this->betterReflectionProperty->isProtectedSet(); | 
| 181: | } | 
| 182: |  | 
| 183: |  | 
| 184: | public function isStatic(): bool | 
| 185: | { | 
| 186: | return $this->betterReflectionProperty->isStatic(); | 
| 187: | } | 
| 188: |  | 
| 189: |  | 
| 190: | public function isFinal(): bool | 
| 191: | { | 
| 192: | return $this->betterReflectionProperty->isFinal(); | 
| 193: | } | 
| 194: |  | 
| 195: |  | 
| 196: | public function isAbstract(): bool | 
| 197: | { | 
| 198: | return $this->betterReflectionProperty->isAbstract(); | 
| 199: | } | 
| 200: |  | 
| 201: |  | 
| 202: | public function isDefault(): bool | 
| 203: | { | 
| 204: | return $this->betterReflectionProperty->isDefault(); | 
| 205: | } | 
| 206: |  | 
| 207: |  | 
| 208: | public function isDynamic(): bool | 
| 209: | { | 
| 210: | return $this->betterReflectionProperty->isDynamic(); | 
| 211: | } | 
| 212: |  | 
| 213: |  | 
| 214: | public function getModifiers(): int | 
| 215: | { | 
| 216: | return $this->betterReflectionProperty->getModifiers(); | 
| 217: | } | 
| 218: |  | 
| 219: | public function getDeclaringClass(): ReflectionClass | 
| 220: | { | 
| 221: | return new ReflectionClass($this->betterReflectionProperty->getImplementingClass()); | 
| 222: | } | 
| 223: |  | 
| 224: |  | 
| 225: |  | 
| 226: |  | 
| 227: | #[ReturnTypeWillChange] | 
| 228: | public function getDocComment() | 
| 229: | { | 
| 230: | return $this->betterReflectionProperty->getDocComment() ?? false; | 
| 231: | } | 
| 232: |  | 
| 233: |  | 
| 234: |  | 
| 235: |  | 
| 236: |  | 
| 237: |  | 
| 238: | public function setAccessible($accessible): void | 
| 239: | { | 
| 240: | } | 
| 241: |  | 
| 242: | public function hasDefaultValue(): bool | 
| 243: | { | 
| 244: | return $this->betterReflectionProperty->hasDefaultValue(); | 
| 245: | } | 
| 246: |  | 
| 247: |  | 
| 248: |  | 
| 249: |  | 
| 250: | #[ReturnTypeWillChange] | 
| 251: | public function getDefaultValue() | 
| 252: | { | 
| 253: | return $this->betterReflectionProperty->getDefaultValue(); | 
| 254: | } | 
| 255: |  | 
| 256: | public function getDefaultValueExpression(): Expr | 
| 257: | { | 
| 258: | return $this->betterReflectionProperty->getDefaultValueExpression(); | 
| 259: | } | 
| 260: |  | 
| 261: |  | 
| 262: |  | 
| 263: |  | 
| 264: | #[ReturnTypeWillChange] | 
| 265: | public function isInitialized($object = null) | 
| 266: | { | 
| 267: | try { | 
| 268: | return $this->betterReflectionProperty->isInitialized($object); | 
| 269: | } catch (Throwable $e) { | 
| 270: | throw new CoreReflectionException($e->getMessage(), 0, $e); | 
| 271: | } | 
| 272: | } | 
| 273: |  | 
| 274: | public function isPromoted(): bool | 
| 275: | { | 
| 276: | return $this->betterReflectionProperty->isPromoted(); | 
| 277: | } | 
| 278: |  | 
| 279: |  | 
| 280: |  | 
| 281: |  | 
| 282: |  | 
| 283: |  | 
| 284: | public function getAttributes(?string $name = null, int $flags = 0): array | 
| 285: | { | 
| 286: | if ($flags !== 0 && $flags !== ReflectionAttribute::IS_INSTANCEOF) { | 
| 287: | throw new ValueError('Argument #2 ($flags) must be a valid attribute filter flag'); | 
| 288: | } | 
| 289: |  | 
| 290: | if ($name !== null && $flags !== 0) { | 
| 291: | $attributes = $this->betterReflectionProperty->getAttributesByInstance($name); | 
| 292: | } elseif ($name !== null) { | 
| 293: | $attributes = $this->betterReflectionProperty->getAttributesByName($name); | 
| 294: | } else { | 
| 295: | $attributes = $this->betterReflectionProperty->getAttributes(); | 
| 296: | } | 
| 297: |  | 
| 298: | return array_map(static fn (BetterReflectionAttribute $betterReflectionAttribute) => ReflectionAttributeFactory::create($betterReflectionAttribute), $attributes); | 
| 299: | } | 
| 300: |  | 
| 301: | public function isReadOnly(): bool | 
| 302: | { | 
| 303: | return $this->betterReflectionProperty->isReadOnly(); | 
| 304: | } | 
| 305: |  | 
| 306: |  | 
| 307: | public function isVirtual(): bool | 
| 308: | { | 
| 309: | return $this->betterReflectionProperty->isVirtual(); | 
| 310: | } | 
| 311: |  | 
| 312: | public function hasHooks(): bool | 
| 313: | { | 
| 314: | return $this->betterReflectionProperty->hasHooks(); | 
| 315: | } | 
| 316: |  | 
| 317: |  | 
| 318: | public function hasHook(PropertyHookType $hookType): bool | 
| 319: | { | 
| 320: | return $this->betterReflectionProperty->hasHook(BetterReflectionPropertyHookType::fromCoreReflectionPropertyHookType($hookType)); | 
| 321: | } | 
| 322: |  | 
| 323: |  | 
| 324: | public function getHook(PropertyHookType $hookType): ?\PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod | 
| 325: | { | 
| 326: | $hook = $this->betterReflectionProperty->getHook(BetterReflectionPropertyHookType::fromCoreReflectionPropertyHookType($hookType)); | 
| 327: | if ($hook === null) { | 
| 328: | return null; | 
| 329: | } | 
| 330: |  | 
| 331: | return new ReflectionMethod($hook); | 
| 332: | } | 
| 333: |  | 
| 334: |  | 
| 335: | public function getHooks(): array | 
| 336: | { | 
| 337: | return array_map( | 
| 338: | static fn (BetterReflectionMethod $betterReflectionMethod): CoreReflectionMethod => new ReflectionMethod($betterReflectionMethod), | 
| 339: | $this->betterReflectionProperty->getHooks(), | 
| 340: | ); | 
| 341: | } | 
| 342: |  | 
| 343: |  | 
| 344: |  | 
| 345: |  | 
| 346: | public function getSettableType(): ?\ReflectionType | 
| 347: | { | 
| 348: | $setHook = $this->betterReflectionProperty->getHook(BetterReflectionPropertyHookType::Set); | 
| 349: | if ($setHook !== null) { | 
| 350: | return ReflectionType::fromTypeOrNull($setHook->getParameters()[0]->getType()); | 
| 351: | } | 
| 352: |  | 
| 353: | if ($this->isVirtual()) { | 
| 354: | return new ReflectionNamedType('never'); | 
| 355: | } | 
| 356: |  | 
| 357: | return $this->getType(); | 
| 358: | } | 
| 359: |  | 
| 360: |  | 
| 361: |  | 
| 362: |  | 
| 363: |  | 
| 364: |  | 
| 365: |  | 
| 366: |  | 
| 367: | public function setRawValue(object $object, $value): void | 
| 368: | { | 
| 369: | if ($this->hasHooks()) { | 
| 370: | throw Exception\NotImplementedBecauseItTriggersAutoloading::create(); | 
| 371: | } | 
| 372: |  | 
| 373: | $this->setValue($object, $value); | 
| 374: | } | 
| 375: |  | 
| 376: |  | 
| 377: |  | 
| 378: |  | 
| 379: | public function __get(string $name) | 
| 380: | { | 
| 381: | if ($name === 'name') { | 
| 382: | return $this->betterReflectionProperty->getName(); | 
| 383: | } | 
| 384: |  | 
| 385: | if ($name === 'class') { | 
| 386: | return $this->betterReflectionProperty->getImplementingClass()->getName(); | 
| 387: | } | 
| 388: |  | 
| 389: | throw new OutOfBoundsException(sprintf('Property %s::$%s does not exist.', self::class, $name)); | 
| 390: | } | 
| 391: |  | 
| 392: | public function getBetterReflection(): BetterReflectionProperty | 
| 393: | { | 
| 394: | return $this->betterReflectionProperty; | 
| 395: | } | 
| 396: | } | 
| 397: |  |