@@ -81,6 +81,12 @@ final class ClassReflection
81
81
/** @var ExtendedPropertyReflection[] */
82
82
private array $ properties = [];
83
83
84
+ /** @var ExtendedPropertyReflection[] */
85
+ private array $ instanceProperties = [];
86
+
87
+ /** @var ExtendedPropertyReflection[] */
88
+ private array $ staticProperties = [];
89
+
84
90
/** @var RealClassClassConstantReflection[] */
85
91
private array $ constants = [];
86
92
@@ -147,6 +153,12 @@ final class ClassReflection
147
153
/** @var array<string, bool> */
148
154
private array $ hasPropertyCache = [];
149
155
156
+ /** @var array<string, bool> */
157
+ private array $ hasInstancePropertyCache = [];
158
+
159
+ /** @var array<string, bool> */
160
+ private array $ hasStaticPropertyCache = [];
161
+
150
162
/**
151
163
* @param PropertiesClassReflectionExtension[] $propertiesClassReflectionExtensions
152
164
* @param MethodsClassReflectionExtension[] $methodsClassReflectionExtensions
@@ -460,6 +472,9 @@ private function allowsDynamicPropertiesExtensions(): bool
460
472
return false ;
461
473
}
462
474
475
+ /**
476
+ * @deprecated Use hasInstanceProperty or hasStaticProperty instead
477
+ */
463
478
public function hasProperty (string $ propertyName ): bool
464
479
{
465
480
if (array_key_exists ($ propertyName , $ this ->hasPropertyCache )) {
@@ -479,13 +494,61 @@ public function hasProperty(string $propertyName): bool
479
494
}
480
495
}
481
496
497
+ // For BC purpose
498
+ if ($ this ->getPhpExtension ()->hasStaticProperty ($ this , $ propertyName )) {
499
+ return $ this ->hasPropertyCache [$ propertyName ] = true ;
500
+ }
501
+
482
502
if ($ this ->requireExtendsPropertiesClassReflectionExtension ->hasProperty ($ this , $ propertyName )) {
483
503
return $ this ->hasPropertyCache [$ propertyName ] = true ;
484
504
}
485
505
486
506
return $ this ->hasPropertyCache [$ propertyName ] = false ;
487
507
}
488
508
509
+ public function hasInstanceProperty (string $ propertyName ): bool
510
+ {
511
+ if (array_key_exists ($ propertyName , $ this ->hasInstancePropertyCache )) {
512
+ return $ this ->hasInstancePropertyCache [$ propertyName ];
513
+ }
514
+
515
+ if ($ this ->isEnum ()) {
516
+ return $ this ->hasInstancePropertyCache [$ propertyName ] = $ this ->hasNativeProperty ($ propertyName );
517
+ }
518
+
519
+ foreach ($ this ->propertiesClassReflectionExtensions as $ i => $ extension ) {
520
+ if ($ i > 0 && !$ this ->allowsDynamicPropertiesExtensions ()) {
521
+ break ;
522
+ }
523
+ if ($ extension ->hasProperty ($ this , $ propertyName )) {
524
+ return $ this ->hasInstancePropertyCache [$ propertyName ] = true ;
525
+ }
526
+ }
527
+
528
+ if ($ this ->requireExtendsPropertiesClassReflectionExtension ->hasInstanceProperty ($ this , $ propertyName )) {
529
+ return $ this ->hasPropertyCache [$ propertyName ] = true ;
530
+ }
531
+
532
+ return $ this ->hasPropertyCache [$ propertyName ] = false ;
533
+ }
534
+
535
+ public function hasStaticProperty (string $ propertyName ): bool
536
+ {
537
+ if (array_key_exists ($ propertyName , $ this ->hasStaticPropertyCache )) {
538
+ return $ this ->hasStaticPropertyCache [$ propertyName ];
539
+ }
540
+
541
+ if ($ this ->getPhpExtension ()->hasStaticProperty ($ this , $ propertyName )) {
542
+ return $ this ->hasStaticPropertyCache [$ propertyName ] = true ;
543
+ }
544
+
545
+ if ($ this ->requireExtendsPropertiesClassReflectionExtension ->hasStaticProperty ($ this , $ propertyName )) {
546
+ return $ this ->hasStaticPropertyCache [$ propertyName ] = true ;
547
+ }
548
+
549
+ return $ this ->hasStaticPropertyCache [$ propertyName ] = false ;
550
+ }
551
+
489
552
public function hasMethod (string $ methodName ): bool
490
553
{
491
554
if (array_key_exists ($ methodName , $ this ->hasMethodCache )) {
@@ -630,6 +693,20 @@ public function evictPrivateSymbols(): void
630
693
631
694
unset($ this ->properties [$ name ]);
632
695
}
696
+ foreach ($ this ->instanceProperties as $ name => $ property ) {
697
+ if (!$ property ->isPrivate ()) {
698
+ continue ;
699
+ }
700
+
701
+ unset($ this ->instanceProperties [$ name ]);
702
+ }
703
+ foreach ($ this ->staticProperties as $ name => $ property ) {
704
+ if (!$ property ->isPrivate ()) {
705
+ continue ;
706
+ }
707
+
708
+ unset($ this ->staticProperties [$ name ]);
709
+ }
633
710
foreach ($ this ->methods as $ name => $ method ) {
634
711
if (!$ method ->isPrivate ()) {
635
712
continue ;
@@ -640,6 +717,7 @@ public function evictPrivateSymbols(): void
640
717
$ this ->getPhpExtension ()->evictPrivateSymbols ($ this ->getCacheKey ());
641
718
}
642
719
720
+ /** @deprecated Use getInstanceProperty or getStaticProperty */
643
721
public function getProperty (string $ propertyName , ClassMemberAccessAnswerer $ scope ): ExtendedPropertyReflection
644
722
{
645
723
if ($ this ->isEnum ()) {
@@ -669,6 +747,15 @@ public function getProperty(string $propertyName, ClassMemberAccessAnswerer $sco
669
747
}
670
748
}
671
749
750
+ // For BC purpose
751
+ if ($ this ->getPhpExtension ()->hasStaticProperty ($ this , $ propertyName )) {
752
+ $ property = $ this ->wrapExtendedProperty ($ this ->getPhpExtension ()->getStaticProperty ($ this , $ propertyName ));
753
+ if ($ scope ->canReadProperty ($ property )) {
754
+ return $ this ->properties [$ key ] = $ property ;
755
+ }
756
+ $ this ->properties [$ key ] = $ property ;
757
+ }
758
+
672
759
if (!isset ($ this ->properties [$ key ])) {
673
760
if ($ this ->requireExtendsPropertiesClassReflectionExtension ->hasProperty ($ this , $ propertyName )) {
674
761
$ property = $ this ->requireExtendsPropertiesClassReflectionExtension ->getProperty ($ this , $ propertyName );
@@ -683,9 +770,83 @@ public function getProperty(string $propertyName, ClassMemberAccessAnswerer $sco
683
770
return $ this ->properties [$ key ];
684
771
}
685
772
773
+ public function getInstanceProperty (string $ propertyName , ClassMemberAccessAnswerer $ scope ): ExtendedPropertyReflection
774
+ {
775
+ if ($ this ->isEnum ()) {
776
+ return $ this ->getNativeProperty ($ propertyName );
777
+ }
778
+
779
+ $ key = $ propertyName ;
780
+ if ($ scope ->isInClass ()) {
781
+ $ key = sprintf ('%s-%s ' , $ key , $ scope ->getClassReflection ()->getCacheKey ());
782
+ }
783
+
784
+ if (!isset ($ this ->instanceProperties [$ key ])) {
785
+ foreach ($ this ->propertiesClassReflectionExtensions as $ i => $ extension ) {
786
+ if ($ i > 0 && !$ this ->allowsDynamicPropertiesExtensions ()) {
787
+ break ;
788
+ }
789
+
790
+ if (!$ extension ->hasProperty ($ this , $ propertyName )) {
791
+ continue ;
792
+ }
793
+
794
+ $ property = $ this ->wrapExtendedProperty ($ extension ->getProperty ($ this , $ propertyName ));
795
+ if ($ scope ->canReadProperty ($ property )) {
796
+ return $ this ->instanceProperties [$ key ] = $ property ;
797
+ }
798
+ $ this ->instanceProperties [$ key ] = $ property ;
799
+ }
800
+ }
801
+
802
+ if (!isset ($ this ->instanceProperties [$ key ])) {
803
+ if ($ this ->requireExtendsPropertiesClassReflectionExtension ->hasInstanceProperty ($ this , $ propertyName )) {
804
+ $ property = $ this ->requireExtendsPropertiesClassReflectionExtension ->getInstanceProperty ($ this , $ propertyName );
805
+ $ this ->instanceProperties [$ key ] = $ property ;
806
+ }
807
+ }
808
+
809
+ if (!isset ($ this ->instanceProperties [$ key ])) {
810
+ throw new MissingPropertyFromReflectionException ($ this ->getName (), $ propertyName );
811
+ }
812
+
813
+ return $ this ->instanceProperties [$ key ];
814
+ }
815
+
816
+ public function getStaticProperty (string $ propertyName , ClassMemberAccessAnswerer $ scope ): ExtendedPropertyReflection
817
+ {
818
+ $ key = $ propertyName ;
819
+ if ($ scope ->isInClass ()) {
820
+ $ key = sprintf ('%s-%s ' , $ key , $ scope ->getClassReflection ()->getCacheKey ());
821
+ }
822
+
823
+ if (!isset ($ this ->staticProperties [$ key ])) {
824
+ if ($ this ->getPhpExtension ()->hasStaticProperty ($ this , $ propertyName )) {
825
+ $ property = $ this ->wrapExtendedProperty ($ this ->getPhpExtension ()->getStaticProperty ($ this , $ propertyName ));
826
+ if ($ scope ->canReadProperty ($ property )) {
827
+ return $ this ->staticProperties [$ key ] = $ property ;
828
+ }
829
+ $ this ->staticProperties [$ key ] = $ property ;
830
+ }
831
+ }
832
+
833
+ if (!isset ($ this ->staticProperties [$ key ])) {
834
+ if ($ this ->requireExtendsPropertiesClassReflectionExtension ->hasStaticProperty ($ this , $ propertyName )) {
835
+ $ property = $ this ->requireExtendsPropertiesClassReflectionExtension ->getStaticProperty ($ this , $ propertyName );
836
+ $ this ->staticProperties [$ key ] = $ property ;
837
+ }
838
+ }
839
+
840
+ if (!isset ($ this ->staticProperties [$ key ])) {
841
+ throw new MissingPropertyFromReflectionException ($ this ->getName (), $ propertyName );
842
+ }
843
+
844
+ return $ this ->staticProperties [$ key ];
845
+ }
846
+
686
847
public function hasNativeProperty (string $ propertyName ): bool
687
848
{
688
- return $ this ->getPhpExtension ()->hasProperty ($ this , $ propertyName );
849
+ return $ this ->getPhpExtension ()->hasNativeProperty ($ this , $ propertyName );
689
850
}
690
851
691
852
public function getNativeProperty (string $ propertyName ): PhpPropertyReflection
0 commit comments