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